#include "bgaimageprocess.h"
#include "qhalconwindow.h"
#include <QDateTime>
#include "xlsxdocument.h"
#include "ImageSaveManager.h"
using namespace HalconCpp;

double distance(QPointF p1, QPointF p2)
{
	return sqrt(pow(p1.x() - p2.x(), 2) + pow(p1.y() - p2.y(), 2));
}

BgaImageProcess::BgaImageProcess()
{
	m_curRes = ResultManager::ERR_MAX;
	m_iVerifyCount = 0;
	m_iInspectCount = 0;
}

void BgaImageProcess::ResetVerifyTest()
{
	m_iVerifyCount = 0;
}

void BgaImageProcess::SetWinHandleAndSavePath(QWidget *widget, QString path, QDateTime time, RUN_INFO ri)
{
	
	m_path = path;
	m_widget = widget;
	m_time = time;
	m_ri = ri;
}

bool BgaImageProcess::InitParameter()
{
	m_inspectParam = BgaPackageManager::getInstance()->GetParamFromFile();
	//m_CamParam = CaliParamManager::getInstance()->GetCameraParam();


	//m_CalobjPose = CaliParamManager::getInstance()->GetPoseParam();
	//m_lp = PgaLayoutManager::getInstance()->GetDefaultLayoutParam();

	//  m_OkPins = PgaLayoutManager::getInstance()->GetDefaultPinsParam();
	/*int c1 = m_CamParam.Length();
	int c2 = m_CalobjPose.Length();*/
	//	m_resultParam.countBallDamaged = 0;
	m_resultParam.countBallMiss = 0;
	m_resultParam.countCap = 0;

	GenEmptyObj(&m_resultParam.regionDamagedBall);
	GenEmptyObj(&m_resultParam.regionDamagedEdge);
	GenEmptyObj(&m_resultParam.regionCap);
	GenEmptyObj(&m_regionSubstrate);
	GenEmptyObj(&m_regionAllCaps);
	GenEmptyObj(&m_resultParam.resultImage);
	m_listInspectEntity.clear();
	m_listCriticalEntity.clear();
	if (m_inspectParam.bResultCali)
	{
		//BgaPackageManager::PACKAGE_INFO info = BgaPackageManager::getInstance()->getPackageInfo();

		if (m_capImage.IsInitialized())
			m_capImage = m_capImage.RotateImage(-90, "constant");// .MirrorImage("column");
		if (m_ballImage.IsInitialized())
			m_ballImage = m_ballImage.RotateImage(-90, "constant");//.MirrorImage("column");
		if (m_substrateImage.IsInitialized())
			m_substrateImage = m_substrateImage.RotateImage(-90, "constant");// .MirrorImage("column");
		if (m_crossMarkImage.IsInitialized())
			m_crossMarkImage = m_crossMarkImage.RotateImage(-90, "constant");// .MirrorImage("column");
	}

	m_pod.ballsPosList.clear();
	m_pod.capsPosList.clear();
	m_pod.meanCapArea = 0;
	return true;
}

void BgaImageProcess::CheckSubstrate(HalconCpp::HImage image)
{
	if (!m_regionSubstrate.IsInitialized())
	{
		qDebug() << "substarte m_regionSubstrate null";
		return;
	}
	QString type = BgaPackageManager::getInstance()->GetPackageType().toUpper(); 
	PACKAGE_INFO info = StaticFunction::GetPackageInfo();
	/*if (type.indexOf("FC1517") != -1 || type.indexOf("SCP105A") != -1 || type.indexOf("SD104A") != -1 || type.indexOf("SCM111") != -1)
	{
		HRegion regionSelect = image.ReduceDomain(m_regionSubstrate).Threshold(100, 255).Connection().SelectShape("area", "and", 10000, 10000000);
		if (regionSelect.CountObj() != 0)
		{
			m_regionSubstrate = m_regionSubstrate.Difference(regionSelect.Union1());
		}
	}*/

	if (type.indexOf("D231SLA2") != -1 || type.indexOf("AP108") != -1 || info.brightBorder == 1)
	{
		HRegion regionSelect = image.ReduceDomain(m_regionSubstrate).EdgesSubPix("canny", 1, 20, 50).SelectShapeXld(HTuple("width").Append(HTuple("height")), "or", HTuple(150).Append(HTuple(150)), HTuple(9999).Append(HTuple(9999))).GenRegionContourXld("filled");
		if (regionSelect.CountObj() != 0)
		{
			//HRegion regionSelect1 = regionSelect.Union1().ShapeTrans("convex");
			//HRegion regionSelect2 = regionSelect1.Difference(regionSelect1.ErosionRectangle1(55, 55));
			m_regionSubstrate = m_regionSubstrate.Difference(regionSelect.Union1().DilationCircle(3.5));
		}
	}
	//else if(type.indexOf("DORADO") != -1 || type.indexOf("ZX225070V1") != -1)
	//{
	//	HRegion regionSelect = image.ReduceDomain(m_regionSubstrate).Threshold(50, 255).Connection().SelectShape("area", "and", 10000, 10000000);
	//	if (regionSelect.CountObj() != 0)
	//	{
	//		m_regionSubstrate = m_regionSubstrate.Difference(regionSelect.Union1());
	//	}
	//}
	else if (type.indexOf("D202SL&SS") != -1)
	{
		HRegion regionSelect = image.ReduceDomain(m_regionSubstrate).Threshold(100, 255).Connection().SelectShape("area", "and", 10000, 10000000);
		if (regionSelect.CountObj() != 0)
		{
			m_regionSubstrate = m_regionSubstrate.Intersection(regionSelect.ShapeTrans("convex") .ErosionCircle(10.5));
		}
	}	
	HRegion regionSelect = image.ReduceDomain(m_regionSubstrate).Threshold(150, 255).Connection().SelectShape("area", "and", m_inspectParam.miniChippingArea, 10000000);
	if (regionSelect.CountObj() == 0)
	{
		qDebug() << "substrate, OK";
	}
	else
	{
		HTuple a, r, c;
		a = regionSelect.AreaCenter(&r, &c);
		for (int i = 0; i < regionSelect.CountObj(); i++)
		{
			INSPECT_ENTITY ie;
			ie.coordinate = QPointF(r[i].D(), c[i].D());
			ie.reason = FAIL_SUBSTRATE_AREA;
			ie.value.substrateArea = a[i];
			ie.reasonDesc = "Substrate damage area";
			ie.parameterDesc = QString("%1 (0 ~ %2)").arg(ie.value.substrateArea).arg(m_inspectParam.miniChippingArea);
			m_listInspectEntity.append(ie);
		}
		qDebug() << "substrate, NG";
	}
	m_resultParam.regionDamagedEdge = regionSelect;
}

HRegion BgaImageProcess::GetCapsRegionNew(HImage imgCap)
{
	HRegion regionCap;
	QString type = BgaPackageManager::getInstance()->GetPackageType().toUpper();
	if (type.indexOf("MI-100") != -1)
	{
		HImage imageGauss = imgCap.GaussFilter(3);
		//	double circle = m_inspectParam.miniCircularity / 100.0;
		HRegion region1 = imageGauss.Threshold(70, 255).FillUp().Connection();
		HRegion regionTemp = region1.SelectShape("circularity", "and", 0.3, 1).OpeningCircle(2.5);
		if (regionTemp.CountObj() == 0)
		{
			return regionTemp;
		}
		HRegion regionAll = regionTemp.SelectShape("area", "and", 110, 99999).Union1().ShapeTrans("convex");
		HRegion region = regionTemp.ClosingCircle(2.5).SelectShape("area", "and", 60, 99999);
		//m_regionTest = regionAll.Difference(region).ErosionRectangle1(5.5, 25.5).Connection().FillUp().SelectShape("area", "and", 10000, 99999999).Union1();
		regionCap = regionAll.Difference(region).ErosionRectangle1(5.5, 25.5).Connection().FillUp().SelectShape("area", "and", 10000, 99999999).SelectShape("height", "and", 200, 500).ShapeTrans("inner_rectangle1").Union1();
		if (m_inspectParam.bResultCali)
		{
			regionCap = regionAll.Difference(region).ErosionRectangle1(25.5, 5.5).Connection().FillUp().SelectShape("area", "and", 10000, 99999999).SelectShape("width", "and", 200, 500).ShapeTrans("inner_rectangle1").Union1();
		}
		m_regionAllBalls = regionAll.DilationCircle(7.5).Difference(regionCap);
		m_resultParam.regionCap = regionCap;
	}
	else if (type.indexOf("T28") != -1)
	{
		HRegion r1 = m_ballImage.GaussFilter(3).Threshold(128, 255).Connection().FillUp().OpeningCircle(3.5).SelectShape("circularity", "and", 0.7, 1).DilationCircle(13.5).Union1().Connection();
		double area1 = r1.SelectShapeStd("max_area", 70).Area();
		HRegion r2 = r1.SelectShape("area", "and", area1*0.8, area1).Union1();
		HRegion r3 = r2.ShapeTrans("convex");
		regionCap = r3.Difference(r2).Connection().OpeningCircle(30.5).Union1();
		m_regionAllBalls = r3.Difference(regionCap);
		//m_resultParam.regionCap = regionCap;
		m_resultParam.regionCap = m_regionAllCaps = m_capImage.GetDomain();
		m_regionSubstrate = m_ballImage.GetDomain().Difference(r3);
	}
	else if (type.indexOf("T32") != -1)
	{
		HRegion r1 = m_ballImage.GaussFilter(3).Threshold(m_meanGray + 30, 255).Connection().FillUp().ClosingCircle(3.5).SelectShape("area", "and", 300, 1000);
		HRegion r2 = r1.DilationCircle(10.5).Union1().Connection().SelectShapeStd("max_area", 70).ShapeTrans("convex");
		m_regionAllBalls = r1.Union1();//.ShapeTrans("convex");
		m_regionSubstrate = m_ballImage.GetDomain().Difference(r2);
		regionCap = m_regionAllCaps;
	}
	else if (type.indexOf("AP108") != -1)
	{
		HRegion r1 = m_ballImage.GaussFilter(3).Threshold(120, 255).Connection().SelectShape("circularity", "and", 0.7, 1).SelectShape("area", "and", 100, 400);
		HRegion r2 = r1.DilationCircle(10.5).Union1().Connection().SelectShapeStd("max_area", 70);
		HRegion r3 = r2.FillUp().Difference(r2).Connection();
		regionCap = r3.SelectShape("height", "and", 60, 100).SelectShape("area", "and", 1500, 4000).Union1();
		m_regionAllBalls = r2.ShapeTrans("convex").Difference(regionCap);
		m_resultParam.regionCap = regionCap;
	}
	return regionCap;
}


void BgaImageProcess::SaveImage(HalconCpp::HImage img, HalconCpp::HRegion reg, QString name)
{
	if (reg.IsInitialized())
	{
		img.ReduceDomain(reg.Union1()).CropDomain().WriteImage("bmp", 0, name.toUtf8());
	}
}

HRegion BgaImageProcess::GetBallsRegions(HImage image)
{
	HRegion regionTemp;
	if (!image.IsInitialized())
	{
		return regionTemp;
	}
	HImage imageGauss = image.GaussFilter(3);
	PACKAGE_INFO info = StaticFunction::GetPackageInfo();
	if (info.capNumbers > 0)
	{
		if (!m_regionAllBalls.IsInitialized())
		{
			qDebug() << "m_regionAllBalls.IsInitialized()==0";
			return m_regionAllBalls;
		}
		imageGauss = image.GaussFilter(3).ReduceDomain(m_regionAllBalls);
	}

	HRegion region1 = imageGauss.Threshold(100, 255).Connection().FillUp();
	//HRegion region1 = imageGauss.Threshold(100, 255).ClosingCircle(2.5).Connection();

	regionTemp = region1.SelectShape((HTuple("circularity").Append("roundness")),"or", (HTuple(0.6).Append(0.6)), (HTuple(1).Append(1))).OpeningCircle(1.5);// .SelectShape("area", "and", 100, 9999);
	if (regionTemp.CountObj() == 0)
	{
		return regionTemp;
	}
	HTuple areah = regionTemp.Area();
	double area1 = areah.TupleMean();
	if (areah.Length() > 2)
	{
		area1 = (areah.TupleSum() - areah.TupleMax() - areah.TupleMin()) *1.0 / (areah.Length() - 2);
	}
	double minA = 0.45;
	double maxA = 2.0;

	QString type = BgaPackageManager::getInstance()->GetPackageType().toUpper();
	/*if (type.indexOf("MERO") != -1 || type.indexOf("S231SLA2") != -1 || type.indexOf("BL5R2") != -1)
	{
		minA = 0.5;
		maxA = 1.5;
	}*/
	HRegion region2 = regionTemp.SelectShape("area", "and", minA*area1, maxA*area1);
	if (region2.CountObj() == 0)
	{
		return region2;
	}
	else if(type.indexOf("BL12") != -1)
	{
		Hlong hv_xy = 50;
		Hlong row1, row2, column1, column2;
		region2.Union1().SmallestRectangle1(&row1, &column1, &row2, &column2);
		
		HObject  ho_Contour, ho_Region;
		HTuple hv_rows, hv_columns;
		hv_rows.Clear();
		hv_rows.Append(row2 - hv_xy);
		hv_rows.Append(row2);
		hv_rows.Append(row2);
		hv_rows.Append(row2 - hv_xy);
		hv_columns.Clear();
		hv_columns[0] = column2;
		hv_columns[1] = column2;
		hv_columns[2] = column2 - hv_xy;
		hv_columns[3] = column2;
		GenContourPolygonXld(&ho_Contour, hv_rows, hv_columns);
		GenRegionContourXld(ho_Contour, &ho_Region, "filled");
		region2 = region2.Union1().Difference(ho_Region).Connection();	
	}
	HRegion	region3 = imageGauss.ReduceDomain(region2.DilationCircle(0.5).Union1().ShapeTrans("convex")).Threshold(100, 255).Connection().FillUp().SelectShape("area", "and", minA*area1, maxA*area1);// .OpeningCircle(2.5);
	double anisometry = 1.8;


	HRegion region4 = region3.SelectShape("anisometry", "and", 1, anisometry);

	//if (type.toUpper().indexOf("QY102") != -1 || type.toUpper().indexOf("S231SLD") != -1 || type.toUpper().indexOf("S231SLA2") != -1 || type.indexOf("BL5R2") != -1)
	{
		region4 = region3;
	}
	HRegion region5 = region4.Union1().Intersection(m_resultParam.regionCap.Union1());
	region4 = region4.Difference(region5).Connection();

	if (region4.CountObj() > 0 && type.indexOf("BL5R2") == -1)
	{
		HTuple contlen;
		RegionFeatures(region4, "contlength", &contlen);
		double con = contlen.TupleMean();
		double dif = m_inspectParam.miniDamagedContLength / 100.0;
		region4 = region4.SelectShape("contlength", "and", con*(1 - dif), con*(1 + dif));
	}

#ifdef QT_DEBUG
	qDebug() << region1.CountObj() << region2.CountObj() << region3.CountObj() << region4.CountObj();
#endif // QT_DEBUG

	return region4.SortRegion("character", "true", "row");
}

BOOL BgaImageProcess::CheckBallCrossMark(HImage image)
{
	BOOL bRet = TRUE;
	HImage imgGauss = image.GaussFilter(3);
	HRegion regionBallsLight = GetBallsRegions(m_ballImage);// .ErosionCircle(0.5);

	HRegion regionOut = regionBallsLight.Union1().Connection();

	//	qDebug() << regionOut.CountObj() << r1.CountObj();
	for (int i = 1; i <= regionOut.CountObj(); i++)
	{
		HRegion r2 = imgGauss.ReduceDomain(regionOut.SelectObj(i)).Threshold(200, 255).FillUp();
		HRegion r3 = imgGauss.ReduceDomain(r2).Threshold(0, 110).Connection().SelectShape("area", "and", 2, 99999);
		if (r3.CountObj() >= 4)
		{
			m_resultParam.regionDamagedBall = m_resultParam.regionDamagedBall.ConcatObj(r2);


			HTuple r, c, a;
			a = r2.AreaCenter(&r, &c);
			for (int i = 0; i < r.Length(); i++)
			{
				INSPECT_ENTITY ie;
				ie.coordinate = QPointF(r[i].D(), c[i].D());
				ie.reason = FAIL_BALL_CM;
				ie.reasonDesc = "Cross Mark. ";
				ie.parameterDesc = "Cross Mark. ";
				m_listInspectEntity.append(ie);
			}

			bRet = FALSE;
		}
	}

	return bRet;
}

void BgaImageProcess::CheckBallShadow(HRegion regionSelect)
{
	PACKAGE_INFO info = StaticFunction::GetPackageInfo();
	//HRegion regionBallsLight = GetBallsRegions(m_ballImage);// .ErosionCircle(0.5);
	HRegion regionOut = regionSelect;
	// m_regionAllBalls = regionBallsLight.Union1();
	int countBall = regionOut.CountObj();
	qDebug() << "ball count: " << countBall;
	{
		double r, c, phi, l1, l2;
		regionOut.Union1().SmallestRectangle2(&r, &c, &phi, &l1, &l2);
		m_pod.ballsCenter.setX(r);
		m_pod.ballsCenter.setY(c);
		m_pod.ballsPhi = phi;
		m_pod.rectWidth = l1;
		m_pod.rectHeight = l2;
	}
	{
		HTuple row, column;
		regionOut.AreaCenter(&row, &column);
		for (int i = 0; i < row.Length(); i++)
		{
			QPointF p(row[i].D(), column[i].D());
			m_pod.ballsPosList.push_back(p);
		}
	}

	if (countBall == info.ballNumbers)
	{
		m_resultParam.countBallMiss = 0;
	}
	else if (countBall > info.ballNumbers)
	{
		m_resultParam.countBallMiss = info.ballNumbers - countBall;
		qDebug() << "ball count exceed:" << -m_resultParam.countBallMiss;
	}
	else
	{
		m_resultParam.countBallMiss = info.ballNumbers - countBall;
		qDebug() << "miss ball:" << m_resultParam.countBallMiss;

		BgaPackageManager *m = BgaPackageManager::getInstance();
		BgaPackageManager::POD_INFO pod = m->GetPodFromFile();

		while (true)
		{
			if (m_pod.ballsPhi - pod.ballsPhi > 1)
			{
				m_pod.ballsPhi -= 1.5708;
			}
			else if (m_pod.ballsPhi - pod.ballsPhi < -1)
			{
				m_pod.ballsPhi += 1.5708;
			}
			else
			{
				break;
			}
		}
		HTuple hv_HomMat2D, hv_HomMat2D2;
		VectorAngleToRigid(pod.ballsCenter.x(), pod.ballsCenter.y(), pod.ballsPhi, m_pod.ballsCenter.x(), m_pod.ballsCenter.y(), m_pod.ballsPhi, &hv_HomMat2D);
		double wScale = m_pod.rectWidth / pod.rectWidth;
		double hScale = m_pod.rectHeight / pod.rectHeight;
		if (wScale > 3)
		{
			wScale = 1;
		}
		if (hScale > 3)
		{
			hScale = 1;
		}

		HomMat2dScale(hv_HomMat2D, wScale, hScale, pod.ballsCenter.x(), pod.ballsCenter.y(), &hv_HomMat2D2);
		QList<QPointF> ballsStd;

		for each (QPointF p in pod.ballsPosList)
		{
			HTuple x, y;
			AffineTransPoint2d(hv_HomMat2D2, p.x(), p.y(), &x, &y);
			ballsStd.push_back(QPointF(x.D(), y.D()));
		}
		QList<QPointF> ballsStdCopy = ballsStd;
		QList<QPointF> balls1 = m_pod.ballsPosList;
		bool bFoundMiss = false;
		QString type = BgaPackageManager::getInstance()->GetPackageType().toUpper();
		if (type.indexOf("T28") != -1)
		{
			bFoundMiss = false;
		}
		else
		{
			int dis = 3;
			while (dis <= 30)
			{
				ballsStd = ballsStdCopy;

				for (int idx = 0; idx < ballsStd.size(); ) {
					const QPointF p = ballsStd[idx];
					int b = 0;
					for each (QPointF p1 in balls1)
					{
						double d = distance(p, p1);
						if (d <= dis)
						{
							b++;
						}
					}
					if (b == 0)
					{
						++idx;
					}
					else
					{
						ballsStd.removeAt(idx);
					}
				}
				if (ballsStd.count() == m_resultParam.countBallMiss)
				{
					bFoundMiss = true;
					break;
				}
				else
				{
					//qDebug() << dis << ballsStd.count() << m_resultParam.countBallMiss;
					dis += 2;
				}
			}
		}

		if (bFoundMiss)
		{
			HObject ho3;
			for each (QPointF p in ballsStd)
			{
				INSPECT_ENTITY ie;
				ie.coordinate = p;
				ie.reason = FAIL_BALL_MISS;
				ie.reasonDesc = "Miss Ball. ";
				ie.parameterDesc = "The ball is badly damaged. ";
				m_listInspectEntity.append(ie);
			}
		}
		else
		{
			/*HObject ho3;
			for each (QPointF p in balls1)
			{
				INSPECT_ENTITY ie;
				ie.coordinate = p;
				ie.reason = FAIL_BALL_MISS;
				ie.reasonDesc = "Miss Ball. ";
				ie.parameterDesc = "The ball is badly damaged. ";
				m_listInspectEntity.append(ie);
			}*/
		}
	}
	
	QString type = BgaPackageManager::getInstance()->GetPackageType().toUpper();
	{
		double circle = m_inspectParam.miniCircularity / 100.0;
		HRegion rdMin3 = regionOut.SelectShape("circularity", "and", 0, circle);
		//if (type.indexOf("BL6") != -1)
		//{
		//	rdMin3 = rdMin3.ConcatObj(regionOut.SelectShape("compactness", "and", 1.2, 999));
		//}
		if (rdMin3.CountObj() > 0)
		{
			HTuple r, c, a, cir;

			a = rdMin3.AreaCenter(&r, &c);
			RegionFeatures(rdMin3, "circularity", &cir);
			for (int i = 0; i < r.Length(); i++)
			{
				INSPECT_ENTITY ie;
				ie.coordinate = QPointF(r[i].D(), c[i].D());
				ie.reason = FAIL_BALL_NOT_ROUND;
				ie.value.circularity = cir[i].D();
				ie.reasonDesc = "The ball is not round enough.";
				ie.parameterDesc = QString("%1 (%2 ~ 100)").arg(QString::number(ie.value.circularity * 100, 'f', 1)).arg(m_inspectParam.miniCircularity);

				m_listInspectEntity.append(ie);
			}
			regionOut = regionOut.Difference(rdMin3);
			m_resultParam.regionDamagedBall = m_resultParam.regionDamagedBall.ConcatObj(rdMin3.Union1());
		}
	}
	if (m_ri.bVarify)
	{
		double circle = m_inspectParam.miniCircularity / 100.0;
		HRegion rdMin3 = regionOut.SelectShape("circularity", "and", circle, circle*1.1);
		if (rdMin3.CountObj() > 0)
		{
			HTuple r, c, a, cir;
			a = rdMin3.AreaCenter(&r, &c);
			RegionFeatures(rdMin3, "circularity", &cir);
			for (int i = 0; i < r.Length(); i++)
			{
				CRITICAL_ENTITY ie;
				ie.coordinate = QPointF(r[i].D(), c[i].D());
				ie.reason = CRITICAL_BALL_NOT_ROUND;
				ie.value.circularity = cir[i].D();
				ie.reasonDesc = "[critical] The ball is not round enough.";
				ie.parameterDesc = QString("%1% (%2% ~ 100%)").arg(QString::number(ie.value.circularity * 100, 'f', 1)).arg(m_inspectParam.miniCircularity);

				m_listCriticalEntity.append(ie);
			}
		}
	}

	HRegion regionModel = regionOut;// .ShapeTrans("outer_circle");
	double areaMeanOut = regionModel.Area().TupleMean();
	double minRatio = m_inspectParam.miniAreaRatio / 100.0;
	double maxRatio = m_inspectParam.maxAreaRatio / 100.0;
	//Hlong threhold;
	//ball area
	{
		HRegion rdMin3 = regionModel.SelectShape("area", "and", 1, areaMeanOut*minRatio);
		HRegion rdMax3 = regionModel.SelectShape("area", "and", areaMeanOut * maxRatio, 900000);// .SelectShape("circularity", "and", 0.1, 0.5);;

	////Hlong threhold;
	////ball area
	//{
	//	HRegion rdMin3 = regionOut.ShapeTrans("outer_circle").SelectShape("area", "and", 1, areaMeanOut*minRatio);
	//	HRegion rdMax3 = regionOut.ShapeTrans("outer_circle").SelectShape("area", "and", areaMeanOut * maxRatio, 900000);// .SelectShape("circularity", "and", 0.1, 0.5);;
	//	if (type.indexOf("SCP105A") != -1)
	//	{
	//		rdMin3 = regionOut.OpeningCircle(4.5).ShapeTrans("outer_circle").SelectShape("area", "and", 1, areaMeanOut*minRatio);
	//		rdMax3 = regionOut.OpeningCircle(4.5).ShapeTrans("outer_circle").SelectShape("area", "and", areaMeanOut * maxRatio, 900000);// .SelectShape("circularity", "and", 0.1, 0.5);;

	//	}
		qDebug() << "area too small: " << rdMin3.CountObj() << "area too big:" << rdMax3.CountObj();

		if (rdMin3.CountObj() > 0)
		{
			HTuple r, c, a;
			a = rdMin3.AreaCenter(&r, &c);
			for (int i = 0; i < r.Length(); i++)
			{
				INSPECT_ENTITY ie;
				ie.coordinate = QPointF(r[i].D(), c[i].D());
				ie.reason = FAIL_BALL_TOO_SMALL;
				ie.value.areaRatio = a[i].D() / areaMeanOut;
				ie.reasonDesc = "The ball is too small. ";
				ie.parameterDesc = QString("%1% (%2% ~ %3%)").arg(QString::number(ie.value.areaRatio*100.0, 'f', 1)).arg(m_inspectParam.miniAreaRatio).arg(m_inspectParam.maxAreaRatio);

				m_listInspectEntity.append(ie);
			}
			regionOut = regionOut.Difference(rdMin3);
		}
		if (rdMax3.CountObj() > 0)
		{
			HTuple r, c, a;
			a = rdMax3.AreaCenter(&r, &c);
			for (int i = 0; i < r.Length(); i++)
			{
				INSPECT_ENTITY ie;
				ie.coordinate = QPointF(r[i].D(), c[i].D());
				ie.reason = FAIL_BALL_TOO_BIG;
				ie.value.areaRatio = a[i].D() / areaMeanOut;
				ie.reasonDesc = "The ball is too big. ";
				ie.parameterDesc = QString("%1% (%2% ~ %3%)").arg(QString::number(ie.value.areaRatio*100.0, 'f', 1)).arg(m_inspectParam.miniAreaRatio).arg(m_inspectParam.maxAreaRatio);
				m_listInspectEntity.append(ie);
			}
			regionOut = regionOut.Difference(rdMax3);
		}

		m_resultParam.regionDamagedBall = m_resultParam.regionDamagedBall.ConcatObj(rdMin3.Union1());
		m_resultParam.regionDamagedBall = m_resultParam.regionDamagedBall.ConcatObj(rdMax3.Union1());
	}

	//critical area
	if (m_ri.bVarify)
	{
		HRegion rdMin3 = regionOut.ShapeTrans("outer_circle").SelectShape("area", "and", areaMeanOut*minRatio, areaMeanOut*(minRatio*1.1));
		HRegion rdMax3 = regionOut.ShapeTrans("outer_circle").SelectShape("area", "and", areaMeanOut *(maxRatio*0.9), areaMeanOut * maxRatio);

		qDebug() << "area critical small: " << rdMin3.CountObj() << "area critical big:" << rdMax3.CountObj();

		if (rdMin3.CountObj() > 0)
		{
			HTuple r, c, a;
			a = rdMin3.AreaCenter(&r, &c);
			for (int i = 0; i < r.Length(); i++)
			{
				CRITICAL_ENTITY ie;
				ie.coordinate = QPointF(r[i].D(), c[i].D());
				ie.reason = CRITICAL_BALL_TOO_SMALL;
				ie.value.areaRatio = a[i].D() / areaMeanOut;
				ie.reasonDesc = "[critical] The ball is too small. ";
				ie.parameterDesc = QString("%1% (%2% ~ %3%)").arg(QString::number(ie.value.areaRatio*100.0, 'f', 1)).arg(m_inspectParam.miniAreaRatio).arg(m_inspectParam.maxAreaRatio);

				m_listCriticalEntity.append(ie);
			}
		}
		if (rdMax3.CountObj() > 0)
		{
			HTuple r, c, a;
			a = rdMax3.AreaCenter(&r, &c);
			for (int i = 0; i < r.Length(); i++)
			{
				CRITICAL_ENTITY ie;
				ie.coordinate = QPointF(r[i].D(), c[i].D());
				ie.reason = CRITICAL_BALL_TOO_BIG;
				ie.value.areaRatio = a[i].D() / areaMeanOut;
				ie.reasonDesc = "[critical] The ball is too big. ";
				ie.parameterDesc = QString("%1% (%2% ~ %3%)").arg(QString::number(ie.value.areaRatio*100.0, 'f', 1)).arg(m_inspectParam.miniAreaRatio).arg(m_inspectParam.maxAreaRatio);

				m_listCriticalEntity.append(ie);
			}
		}
	}

	//shadow ratio 
	double lowGray = 180;
	double erosionValue = 2.5;

	{
		HRegion rd33 = m_ballImage.GaussFilter(3).ReduceDomain(regionOut.ErosionCircle(erosionValue).Union1()).Threshold(0, lowGray).Connection();
		HRegion rd3 = rd33.SelectShape("area", "and", areaMeanOut*m_inspectParam.miniDamagedRatio / 100.0, areaMeanOut);
		qDebug() << "shadow too big: " << rd3.CountObj();

		if (rd3.CountObj() == 0)
		{
			m_pod.maxShadowRatio = 100 * rd33.Area().TupleMax().D() / areaMeanOut;
			m_pod.minShadowRatio = 100 * rd33.Area().TupleMin().D() / areaMeanOut;
			m_pod.meanShadowRatio = 100 * rd33.Area().TupleMean().D() / areaMeanOut;
			qDebug() << areaMeanOut << m_pod.minShadowRatio << "%," << m_pod.maxShadowRatio << "%," << m_pod.meanShadowRatio << "%";
		}
		else
		{
			HTuple r, c, a;
			a = rd3.AreaCenter(&r, &c);
			for (int i = 0; i < r.Length(); i++)
			{
				INSPECT_ENTITY ie;
				ie.coordinate = QPointF(r[i].D(), c[i].D());
				ie.reason = FAIL_BALL_SHADOW_TOO_BIG;
				ie.value.shadowRatio = a[i].D() / areaMeanOut;
				//ie.reasonDesc = QString("Ball's shadow is too big: %1% [0 ~ %2]").arg(QString::number(ie.value.shadowRatio*100.0, 'f', 1)).arg(m_inspectParam.miniDamagedRatio);
				ie.reasonDesc = "The ball's shadow is too big. ";
				ie.parameterDesc = QString("%1 (0 ~ %2)").arg(QString::number(ie.value.shadowRatio*100.0, 'f', 1)).arg(m_inspectParam.miniDamagedRatio);

				m_listInspectEntity.append(ie);
			}

		}
		m_resultParam.regionDamagedBall = m_resultParam.regionDamagedBall.ConcatObj(rd3.Union1());

		if (m_ri.bVarify)
		{
			HRegion rd4 = rd33.SelectShape("area", "and", areaMeanOut*(m_inspectParam.miniDamagedRatio*0.9) / 100.0, areaMeanOut*m_inspectParam.miniDamagedRatio / 100.0);
			qDebug() << "shadow critical big: " << rd4.CountObj();
			if (rd4.CountObj() > 0)
			{
				HTuple r, c, a;
				a = rd4.AreaCenter(&r, &c);
				for (int i = 0; i < r.Length(); i++)
				{
					CRITICAL_ENTITY ie;
					ie.coordinate = QPointF(r[i].D(), c[i].D());
					ie.reason = CRITICAL_BALL_SHADOW_TOO_BIG;
					ie.value.shadowRatio = a[i].D() / areaMeanOut;
					//ie.reasonDesc = QString("Ball's shadow is too big: %1% [0 ~ %2]").arg(QString::number(ie.value.shadowRatio*100.0, 'f', 1)).arg(m_inspectParam.miniDamagedRatio);
					ie.reasonDesc = "[critical] The ball's shadow is too big. ";
					ie.parameterDesc = QString("%1 (0 ~ %2)").arg(QString::number(ie.value.shadowRatio*100.0, 'f', 1)).arg(m_inspectParam.miniDamagedRatio);

					m_listCriticalEntity.append(ie);
				}
			}
		}
	}

	if (info.capNumbers > 0)
	{
		HImage imgCap = m_capImage.ReduceDomain(m_regionAllCaps.Union1());
		try
		{
			m_resultParam.resultImage = imgCap.PaintGray(m_ballImage);
			m_resultParam.resultImage = m_substrateImage.ReduceDomain(m_regionSubstrate).PaintGray(m_resultParam.resultImage);
		}
		catch (HException &HDevExpDefaultException)
		{

			//HTuple hv_Exception, hv_Value, hv_ErrMsg;
			//HDevExpDefaultException.ToHTuple(&hv_Exception);
			//
			//HException::GetExceptionData(hv_Exception, "error_code", &hv_Value);
			//HException::GetExceptionData(hv_Exception, "error_msg", &hv_ErrMsg);
			QString str = QString::fromStdString(HDevExpDefaultException.ErrorMessage().Text()).remove("HALCON");

			qDebug() << "Exception 1:" << str;
		}
	}
	else
	{
		try
		{
			m_resultParam.resultImage = m_substrateImage.ReduceDomain(m_regionSubstrate).PaintGray(m_ballImage);
		}
		catch (HException &HDevExpDefaultException)
		{

			QString str = QString::fromStdString(HDevExpDefaultException.ErrorMessage().Text()).remove("HALCON");
			qDebug() << "Exception 2:" << str;
		}
	}
}


BOOL BgaImageProcess::CheckCapacitorsT28()
{
	HRegion r = GetCapsRegionNew(m_capImage);
	m_regionAllCaps = r;
	double dd, mm;
	mm = m_regionAllCaps.Intensity(m_capImage, &dd);

	PACKAGE_INFO info = StaticFunction::GetPackageInfo();

	HImage image = m_capImage.ReduceDomain(m_regionAllCaps);
	HRegion r1 = image.GaussFilter(3).Threshold(mm + 40, 255).Connection().FillUp();// .SelectShape("area", "and", 200, 500);
	HRegion caps = r1.SelectShape("area", "and", 200, 800);
	double capArea = caps.Area().TupleMean();
	double dif = 0.4;
	QString appName = QCoreApplication::applicationName();
	QSettings app(appName, "Debug");
	int d = app.value("maxCapDiff").toInt();
	if (d > 0)
	{
		dif = d / 100.0;
	}
	HRegion regionCaps = r1.SelectShape("area", "and", capArea*(1 - dif), capArea * 3);
	Hlong countCaps = regionCaps.CountObj();
	if (countCaps > 0)
	{
		double row, column;
		regionCaps.Union1().ShapeTrans("rectangle1").AreaCenter(&row, &column);
		m_pod.capsCenter.setX(row);
		m_pod.capsCenter.setY(column);
	}
	else
	{
		return FALSE;
	}
	for (int i = 1; i <= countCaps; i++)
	{
		HRegion r = regionCaps.SelectObj(i);
		double row, column;
		r.AreaCenter(&row, &column);
		m_pod.capsPosList.push_back(QPointF(row, column));
	}
	m_resultParam.regionCap = regionCaps.Union1().FillUp();
	m_resultParam.countCap = regionCaps.CountObj();

	if (m_resultParam.countCap < info.capNumbers)
	{
		return FALSE;
	}
	return TRUE;
}

BOOL BgaImageProcess::CheckCapacitorsBase(double threshold, double min, double max, int filter = 3, double dif = 0.33)
{
	HRegion r = GetCapsRegionNew(m_capImage);
	m_regionAllCaps = r;

	PACKAGE_INFO info = StaticFunction::GetPackageInfo();

	HImage image = m_capImage.GaussFilter(filter).ReduceDomain(m_regionAllCaps.Union1());
	HRegion r1 = image.Threshold(threshold, 255).Connection().FillUp();// .SelectShape("area", "and", 200, 500);
	HRegion caps = r1.SelectShape("area", "and", min, max);
	double capArea = caps.Area().TupleMean();
	QString appName = QCoreApplication::applicationName();
	QSettings app(appName, "Debug");
	int d = app.value("maxCapDiff").toInt();
	if (d > 0)
	{
		dif = d / 100.0;
	}
	HRegion regionCaps = r1.SelectShape("area", "and", capArea*(1 - dif), capArea *(1 + dif));
	Hlong countCaps = regionCaps.CountObj();
	qDebug() << "caps:" << r1.CountObj() << countCaps;
	if (countCaps > 0)
	{
		double row, column;
		regionCaps.Union1().ShapeTrans("rectangle1").AreaCenter(&row, &column);
		m_pod.capsCenter.setX(row);
		m_pod.capsCenter.setY(column);
	}
	else
	{
		return FALSE;
	}
	for (int i = 1; i <= countCaps; i++)
	{
		HRegion r = regionCaps.SelectObj(i);
		double row, column;
		r.AreaCenter(&row, &column);
		m_pod.capsPosList.push_back(QPointF(row, column));
	}
	m_resultParam.regionCap = regionCaps.Union1().FillUp();
	m_resultParam.countCap = regionCaps.CountObj();

	if (m_resultParam.countCap < info.capNumbers)
	{
		return FALSE;
	}
	return TRUE;
}

BOOL BgaImageProcess::CheckCapacitors2()
{
	/*if (!m_inspectParam.bCapDamaged)
	{
		return TRUE;
	}*/
	QString type = BgaPackageManager::getInstance()->GetPackageType().toUpper();
	if (type.indexOf("T28") != -1)
	{
		return CheckCapacitorsT28();
	}
	else if (type.indexOf("AP108") != -1)
	{
		return CheckCapacitorsBase(150, 200, 400);
	}

	HRegion r = GetCapsRegionNew(m_capImage);
	m_regionAllCaps = r;
	PACKAGE_INFO info = StaticFunction::GetPackageInfo();
	HImage image = m_capImage.GaussFilter(3).ReduceDomain(r);
	double capArea = info.capArea == 0 ? 800 : info.capArea;
	HRegion caps = image.Threshold(50, 255).Connection().SelectShape("area", "and", capArea*0.6, capArea *1.4);
	Hlong countCaps = caps.CountObj();
	if (countCaps > 0)
	{
		double row, column;
		caps.Union1().ShapeTrans("rectangle1").AreaCenter(&row, &column);
		m_pod.capsCenter.setX(row);
		m_pod.capsCenter.setY(column);
	}
	for (int i = 1; i <= countCaps; i++)
	{
		HRegion r = caps.SelectObj(i);
		double row, column;
		r.AreaCenter(&row, &column);
		m_pod.capsPosList.push_back(QPointF(row, column));
	}
	if (countCaps == 0)
	{
		return FALSE;
	}

	HTuple area = caps.Area();
	int max = area.TupleMax();
	int min = area.TupleMin();
	double mean = (area.TupleSum() - max - min) / (area.Length() - 2.0);
	m_pod.meanCapArea = mean;

	HRegion regionCaps;
	GenEmptyObj(&regionCaps);
	double dif = 0.33;
	QString appName = QCoreApplication::applicationName();
	QSettings app(appName, "Debug");
	int d = app.value("maxCapDiff").toInt();
	if (d > 0)
	{
		dif = d / 100.0;
	}
	for (int i = 1; i <= countCaps; i++)
	{
		HRegion r = caps.SelectObj(i);

		if (r.Area().I() <= mean * (1 + dif) && r.Area().I() >= mean * (1 - dif))
		{
			regionCaps = regionCaps.ConcatObj(r);
		}
		else {
			qDebug() << "cap area error, mean:" << mean << r.Area().I();

		}
	}

	m_resultParam.regionCap = regionCaps.Union1().FillUp();
	m_resultParam.countCap = regionCaps.CountObj();

	if (m_resultParam.countCap < info.capNumbers)
	{
		//INSPECT_ENTITY ie;
		////	ie.coordinate = QPointF(r[i].D(), c[i].D());
		//ie.reason = FAIL_CAP_AREA;
		////ie.value.areaRatio = a[i].D() / areaMeanOut;
		//ie.reasonDesc = "The capacitor was damaged";


		BgaPackageManager *m = BgaPackageManager::getInstance();
		BgaPackageManager::POD_INFO pod = m->GetPodFromFile();

		double x = m_pod.capsCenter.x() - pod.capsCenter.x();
		double y = m_pod.capsCenter.y() - pod.capsCenter.y();

		QList<QPointF> capsStd;

		for each (QPointF p in pod.capsPosList)
		{
			capsStd.push_back(QPointF(p.x() + x, p.y() + y));
		}

		QList<QPointF> balls1 = m_pod.capsPosList;
		int dis = 10;
		while (dis <= 30)
		{
			for (int idx = 0; idx < capsStd.size(); ) {
				const QPointF p = capsStd[idx];
				BOOL b = FALSE;
				for each (QPointF p1 in balls1)
				{
					double d = distance(p, p1);
					if (d <= dis)
					{
						capsStd.removeAt(idx);
						b = TRUE;
						break;
					}
				}
				if (!b)
				{
					++idx;
				}
			}
			if (capsStd.count() == info.capNumbers - m_resultParam.countCap)
			{
				break;
			}
			else {
				dis++;
			}
		}
		if (capsStd.count() == info.capNumbers - m_resultParam.countCap)
		{
			for each (QPointF p in capsStd)
			{
				INSPECT_ENTITY ie;
				ie.coordinate = p;
				ie.reason = FAIL_CAP_AREA;
				ie.reasonDesc = "Capacitor damaged. ";
				ie.parameterDesc = "The capacitor is damaged. ";
				m_listInspectEntity.append(ie);
			}
		}
		return FALSE;
	}
	else {
		return TRUE;
	}

}

BgaPackageManager::POD_INFO BgaImageProcess::GetPod()
{
	return m_pod;
}


void BgaImageProcess::CheckAllBalls()
{
	PACKAGE_INFO info = StaticFunction::GetPackageInfo();

	HRegion regionSelect = GetBallsRegions(m_ballImage);
	
	if (!regionSelect.IsInitialized())//|| m_resultParam.countBallMiss != 0)
	{
		m_resultParam.countBallMiss = info.ballNumbers;
		m_resultParam.resultImage = m_ballImage;
		return;
	}

	m_regionAllBalls = regionSelect.Union1();

	HRegion regionInner = m_regionAllBalls.FillUp().ShapeTrans("convex").DilationCircle(info.innerGap).ShapeTrans("rectangle2");

	HRegion regionOuter = regionInner.DilationCircle(info.edgeGap).ShapeTrans("rectangle2");
	m_regionSubstrate = regionOuter.Difference(regionInner);
	QString type = BgaPackageManager::getInstance()->GetPackageType().toUpper();
	if (type.indexOf("FP8") != -1)//pin1
	{
		Hlong hv_xy = 20;
		Hlong row1, row2, column1, column2;
		regionInner.Union1().SmallestRectangle1(&row1, &column1, &row2, &column2);
		double row, column, phi, len1, len2;
		regionInner.Union1().SmallestRectangle2(&row, &column, &phi, &len1, &len2);
		HTuple Cos, Sin;
		TupleCos(phi, &Cos);
		TupleSin(phi, &Sin);
		HTuple RB_X = len1 * Cos + len2 * Sin;
		HTuple RB_Y = len1 * Sin - len2 * Cos;

		HObject ho_Region;

		/*HTuple hv_rows, hv_columns;
		hv_rows.Clear();
		hv_rows.Append(row2 + hv_xy);
		hv_rows.Append(row2 + hv_xy);
		hv_rows.Append(row2 - hv_xy);
		hv_rows.Append(row2 + hv_xy);
		hv_columns.Clear();
		hv_columns[0] = column2 - hv_xy;
		hv_columns[1] = column2 + hv_xy;
		hv_columns[2] = column2 + hv_xy;
		hv_columns[3] = column2 - hv_xy;
		GenContourPolygonXld(&ho_Contour, hv_rows, hv_columns);
		GenRegionContourXld(ho_Contour, &ho_Region, "filled");*/
		//GenRectangle1(&ho_Region, RB_X - hv_xy, RB_Y - hv_xy, RB_X + hv_xy, RB_Y + hv_xy);
		//m_regionSubstrate = m_regionSubstrate.Union1().Difference(ho_Region);
		GenRectangle1(&ho_Region, row - RB_Y - hv_xy, column + RB_X - hv_xy, row - RB_Y + hv_xy, column + RB_X + hv_xy);
		m_regionSubstrate = m_regionSubstrate.Union1().Difference(ho_Region);
	}

	if (type.indexOf("BL6") != -1 || type.indexOf("BL5R2") != -1)
	{
		Hlong hv_xy = 50;
		Hlong row1, row2, column1, column2;
		m_regionAllBalls.Union1().SmallestRectangle1(&row1, &column1, &row2, &column2);

		HObject  ho_Contour, ho_Region;
		HTuple hv_rows, hv_columns;
		hv_rows.Clear();
		hv_rows.Append(row2 - hv_xy);
		hv_rows.Append(row2);
		hv_rows.Append(row2);
		hv_rows.Append(row2 - hv_xy);
		hv_columns.Clear();
		hv_columns[0] = column2;
		hv_columns[1] = column2;
		hv_columns[2] = column2 - hv_xy;
		hv_columns[3] = column2;
		GenContourPolygonXld(&ho_Contour, hv_rows, hv_columns);
		GenRegionContourXld(ho_Contour, &ho_Region, "filled");
		m_regionAllBalls = m_regionAllBalls.Union1().Difference(ho_Region).Connection();
		m_regionSubstrate = m_regionSubstrate.Union1().Difference(ho_Region);
	}

	if (regionSelect.CountObj() == 0)//|| m_resultParam.countBallMiss != 0)
	{
		m_resultParam.countBallMiss = info.ballNumbers;
		m_resultParam.resultImage = m_ballImage;
		return;
	}

	if (!m_inspectParam.bBallDamaged)
	{
		return;
	}

	CheckBallShadow(m_regionAllBalls.Connection());
}

void BgaImageProcess::GenFullImageT28()
{
	PACKAGE_INFO info = StaticFunction::GetPackageInfo();
	int c = m_ballImageList.count();
	QList<HImage> imgListBall;
	//QList<HImage> imgListCap;
	//QList<HImage> imgListSub;
	//QList<HImage> imgListCM;
	HImage ImagePart, ImagePart2;
	for (int i = 0; i < c; i++)
	{
		int k = i;
		if (i == 0)
		{
			k = 2;
		}
		else if (i == 2)
		{
			k = 0;
		}
		
		HImage imageBall = m_ballImageList[k].CopyImage().RotateImage(90, "constant");
		HImage imageCap;
		//HImage imageCrossMark;
		HImage imageSubstrate = m_substrateImageList[k].CopyImage().RotateImage(90, "constant");;
		Hlong Width, Height;
		imageBall.GetImageSize(&Width, &Height);
		HRegion Rectangle;
		if (i < 2)
		{

			/*if (Index1 = 1 or Index1 = 2)
				gen_rectangle1(Rectangle, 1000, 0, 10000, 20000)
			else
				gen_rectangle1(Rectangle, 0, 0, 4096 - 1000, 20000)
				endif*/
			GenRectangle1(&Rectangle, 1000, 0, Height, Width);
		}
		else
		{
			GenRectangle1(&Rectangle, 0, 0, Height - 1000, Width);
		}


		HRegion regionS1 = imageBall.ReduceDomain(Rectangle).GaussFilter(3).Threshold(180, 255).DilationCircle(10.5).Union1().Connection().SelectShapeStd("max_area", 70);
		double row, column, phi, len1, len2;
		regionS1.FillUp().Difference(regionS1).Connection().SelectShape("area", "and", 15000, 99999).Union1().SmallestRectangle2(&row, &column, &phi, &len1, &len2);
		double pp = phi * 180.0 / M_PI;
		if (pp >= 0)
		{
			pp = 90 - pp;
		}
		else
		{
			pp = -90 - pp;
		}
		imageBall = imageBall.RotateImage(pp, "constant");
		imageSubstrate = imageSubstrate.RotateImage(pp, "constant");
		/*if (info.capNumbers > 0)
		{
			imageCap = m_capImageList[i].RotateImage(-phi * 180 / M_PI, "constant");
		}*/
	/*	if (info.crossMark)
		{
			imageCrossMark = m_crossMarkImageList[k].RotateImage(pp, "constant");
		}*/
		/*HRegion RegionUnion = imageBall.ReduceDomain(Rectangle).GaussFilter(3).Threshold(180, 255).DilationCircle(10.5).Union1();
		regionS1 = RegionUnion.Connection().SelectShapeStd("max_area", 70);
		HRegion RegionFillUp1 = RegionUnion.Difference(regionS1).Connection().SelectShape("height", "and", 800, 1500).SelectShapeStd("max_area", 70).FillUp();
		HRegion RegionOpening = RegionFillUp1.OpeningCircle(50.5);*/

		HRegion RegionFillUp1;
		int low1 = 150;
		while (true)
		{
			HRegion regionC1 = imageSubstrate.GaussFilter(3).Threshold(low1, 255).OpeningCircle(2.5).DilationCircle(11.5).Union1().Connection();
			regionS1 = regionC1.SelectShapeStd("max_area", 70);
			RegionFillUp1 = regionC1.Difference(regionS1).SelectShape("height", "and", 1000, 999999).FillUp();// SelectShapeStd("max_area", 70).FillUp();
			if (RegionFillUp1.CountObj() == 1 || low1 < 80)
			{
				break;
			}
			else
			{
				//qDebug() << RegionFillUp1.CountObj() << low1 << i;
				low1 -= 5;
			}
		} 
		HRegion RegionOpening = RegionFillUp1.OpeningCircle(45.5);

		double Row, Column;
		RegionOpening.AreaCenter(&Row, &Column);
	
		HRegion Rectangle00;
		HRegion regionBall, regionSub;
		HRegion Rectangle6;
		if (i == 0)
		{
			GenRectangle1(&Rectangle6, Row, Column, Row + 2000, Column + 2000);
			GenRectangle1(&Rectangle00, Row + 200, Column - 15, Row + 1000, Column + 15);
		}
		else if (i == 1)
		{
			GenRectangle1(&Rectangle6, Row, 0, Row + 2000, Column);
			GenRectangle1(&Rectangle00, Row + 200, Column - 15, Row + 1000, Column + 15);
		}
		else if (i == 2)
		{
			GenRectangle1(&Rectangle6, 0, 0, Row, Column); 
			GenRectangle1(&Rectangle00, Row - 1000, Column - 15, Row + 200, Column + 15);
		}
		else if (i == 3)
		{
			GenRectangle1(&Rectangle6, 0, Column, Row, Column + 2000);
			GenRectangle1(&Rectangle00, Row - 1000, Column - 15, Row + 200, Column + 15);
		}
		HRegion SelectedRegions = imageBall.GaussFilter(3).ReduceDomain(Rectangle6).Threshold(180, 255).Connection().SelectShape("area", "and", 250, 700).DilationCircle(15.5).Union1().Connection().SelectShapeStd("max_area", 70);

		HRegion ConnectedRegions6 = SelectedRegions.FillUp().Difference(SelectedRegions).Connection();		
		double areaMax = ConnectedRegions6.SelectShapeStd("max_area", 70).Area();
		HRegion SelectedRegions7 = ConnectedRegions6.SelectShape("area", "and", areaMax*0.9, areaMax);
		regionBall = SelectedRegions.FillUp().Difference(SelectedRegions7);
		//regionCap = SelectedRegions7.Union1();
		Hlong Row1, Column1, Row21, Column21;
		RegionOpening.SmallestRectangle1(&Row1, &Column1, &Row21, &Column21);
		Hlong Row12, Column12, Row2, Column2;
		regionBall.SmallestRectangle1(&Row12, &Column12, &Row2, &Column2);
		HRegion RegionTrans2 = regionBall.ShapeTrans("rectangle1");
		
		if (i == 0)
		{
			//two ball
			{
				//SaveImage(imageBall, regionBall, "e:/regionBall00");
				RegionFillUp1 = imageBall.GaussFilter(3).ReduceDomain(Rectangle00).Threshold(120, 255).DilationCircle(10.5).Union1().Connection().SelectShapeStd("max_area", 70).ErosionCircle(10.5);
				Hlong Row11, Column11, Row22, Column22;
				RegionFillUp1.SmallestRectangle1(&Row11, &Column11, &Row22, &Column22);
				HRegion circle1, circle2;
				GenCircle(&circle1, Row22 + 55, (Column11 + Column22) / 2, 20);
				GenCircle(&circle2, Row22 + 125, (Column11 + Column22) / 2, 20);
				regionBall = regionBall.ConcatObj(circle1).ConcatObj(circle2).Union1().Connection().SelectShapeStd("max_area", 70);
				//SaveImage(imageBall, regionBall, "e:/regionBall1");
			}

			/*HRegion Rectangle5;
			GenRectangle1(&Rectangle5, Row1, 0, 5120, 5120);
			HRegion RegionIntersection = RegionFillUp1.Intersection(Rectangle5);*/

			//ImagePart = imageCap.ReduceDomain(RegionIntersection).CropDomain();

			HRegion r1;
			GenRectangle1(&r1, Row12, Column12, Row2 + info.edgeGap, Column2 + info.edgeGap);
			regionSub = r1.Difference(RegionTrans2);
		}
		else if (i == 1)
		{
			//two ball
			{
				RegionFillUp1 = imageBall.GaussFilter(3).ReduceDomain(Rectangle00).Threshold(120, 255).DilationCircle(10.5).Union1().Connection().SelectShapeStd("max_area", 70).ErosionCircle(10.5);

				Hlong Row11, Column11, Row22, Column22;
				RegionFillUp1.SmallestRectangle1(&Row11, &Column11, &Row22, &Column22);
				HRegion circle1, circle2;
				GenCircle(&circle1, Row22 + 55, (Column11 + Column22) / 2, 18);
				GenCircle(&circle2, Row22 + 125, (Column11 + Column22) / 2, 18);
				regionBall = regionBall.Difference(circle1).Difference(circle2).Union1();
			}
			
			HRegion r1;
			GenRectangle1(&r1, Row12, Column12 - info.edgeGap, Row2 + info.edgeGap, Column2);
			regionSub = r1.Difference(RegionTrans2);
			//SaveImage(imageBall, regionBall, "e:/regionBall2");
		}
		else if (i == 2)
		{
			//two ball
			{
				RegionFillUp1 = imageBall.GaussFilter(3).ReduceDomain(Rectangle00).Threshold(120, 255).DilationCircle(10.5).Union1().Connection().SelectShapeStd("max_area", 70).ErosionCircle(10.5);

				Hlong Row11, Column11, Row22, Column22;
				RegionFillUp1.SmallestRectangle1(&Row11, &Column11, &Row22, &Column22);
				HRegion circle1, circle2;
				GenCircle(&circle1, Row11 - 55, (Column11 + Column22) / 2, 18);
				GenCircle(&circle2, Row11 - 125, (Column11 + Column22) / 2, 18);
				regionBall = regionBall.Difference(circle1).Difference(circle2).Union1();
			}
			HRegion r1;
			GenRectangle1(&r1, Row12 - info.edgeGap, Column12 - info.edgeGap, Row2, Column2);
			regionSub = r1.Difference(RegionTrans2);
			//SaveImage(imageBall, regionBall, "e:/regionBall3");
		}
		else if (i == 3)
		{
			//two ball
			{
				RegionFillUp1 = imageBall.GaussFilter(3).ReduceDomain(Rectangle00).Threshold(120, 255).DilationCircle(10.5).Union1().Connection().SelectShapeStd("max_area", 70).ErosionCircle(10.5);

				Hlong Row11, Column11, Row22, Column22;
				RegionFillUp1.SmallestRectangle1(&Row11, &Column11, &Row22, &Column22);
				HRegion circle1, circle2;
				GenCircle(&circle1, Row11 - 55, Column, 20);
				GenCircle(&circle2, Row11 - 125, Column, 20);
				regionBall = regionBall.ConcatObj(circle1).ConcatObj(circle2).Union1().Connection().SelectShapeStd("max_area", 70);
			}
			//SaveImage(imageBall, regionBall, "e:/regionBall4");
			HRegion r1;
			GenRectangle1(&r1, Row12 - info.edgeGap, Column12, Row2, Column2 + info.edgeGap);
			regionSub = r1.Difference(RegionTrans2);

		/*	HRegion Rectangle5;
			GenRectangle1(&Rectangle5, 0, 0, Row1, 5120);
			HRegion RegionIntersection = RegionFillUp1.Intersection(Rectangle5);
			ImagePart2 = imageCap.ReduceDomain(RegionIntersection).CropDomain();*/
		}

	/*	{
			HTuple hRows, hColuomns;
			regionCap.Union1().GetRegionPoints(&hRows, &hColuomns);
			HTuple hValues = imageCap.GetGrayval(hRows, hColuomns);;
			imageBall.SetGrayval(hRows, hColuomns, hValues);
		}*/

		{
			HTuple hRows, hColuomns;
			regionSub.Union1().GetRegionPoints(&hRows, &hColuomns);
			HTuple hValues = imageSubstrate.GetGrayval(hRows, hColuomns);
			imageBall.SetGrayval(hRows, hColuomns, hValues);
		}
		imageBall = imageBall.ReduceDomain(regionBall.ConcatObj(regionSub).Union1()).CropDomain();
		imgListBall.append(imageBall);
	}
	//Hlong Width, Width2, Height, Height2;
	//ImagePart.GetImageSize(&Width, &Height);
	//ImagePart2.GetImageSize(&Width2, &Height2);
	//HImage ImgCapMidPart, ImgCapMidFull;
	//GenImageConst(&ImgCapMidPart, "byte", Width, Height + Height2);
	//GenImageProto(ImgCapMidPart, &ImgCapMidFull, 0);
	//{
	//	HTuple rows, columns;
	//	ImagePart2.GetDomain().GetRegionPoints(&rows, &columns);
	//	HTuple hValues = ImagePart2.GetGrayval(rows, columns);
	//	ImgCapMidFull.SetGrayval(rows, columns + (Width - Width2) / 2, hValues);
	//}
	//{
	//	HTuple rows, columns;
	//	ImagePart.GetDomain().GetRegionPoints(&rows, &columns);
	//	HTuple hValues = ImagePart.GetGrayval(rows, columns);
	//	ImgCapMidFull.SetGrayval(rows + Height2, columns, hValues);
	//}
	Hlong maxR = 0;
	Hlong maxC = 0;
	Hlong mergeGap = 5;
	for (int i = 0; i < imgListBall.count(); i++)
	{
		Hlong w, h;
		HImage imageBall = imgListBall[i];
		imageBall.GetImageSize(&w, &h);
		if (w > maxC)
		{
			maxC = w;
		}
		if (h > maxR)
		{
			maxR = h;
		}
		/*QString str = QString("g:/imageBall%1.bmp").arg(i + 1);
		imageBall.WriteImage("bmp", 0, str.toStdString().c_str());*/
	}
	HImage img, imgFull;
	GenImageConst(&img, "byte", (maxC + mergeGap) * 2, (maxR + mergeGap) * 2);
	GenImageProto(img, &imgFull, 0);
	Hlong offsetR[4] = { maxR + mergeGap * 2 , maxR + mergeGap * 2, 0, 0 };
	Hlong offsetC[4] = { maxC + mergeGap * 2 ,  0, 0, maxC + mergeGap * 2 };
	for (int i = 0; i < imgListBall.count(); i++)
	{
		HImage imageBall = imgListBall[i];
		HTuple rows, columns;
		imageBall.GetDomain().GetRegionPoints(&rows, &columns);
		HTuple hValues = imageBall.GetGrayval(rows, columns);
		imgFull.SetGrayval(rows + offsetR[i], columns + offsetC[i], hValues);
	}
	//imgFull.WriteImage("bmp", 0, "e:/imgFull1");
	//middle caps
	Hlong Width5, Width6, Height5, Height6;
	imgFull.GetImageSize(&Width5, &Height5);
	m_ballImage = m_substrateImage = imgFull.RotateImage(90, "constant");
	HImage imageCap = m_capImageList[0].RotateImage(90, "constant");
	HRegion RegionUnion = imageCap.GaussFilter(3).Threshold(150, 255).Connection().SelectShape("roundness", "and", 0.8, 1).SelectShape("area", "and", 550, 1000).DilationCircle(20.5).Union1();
	HRegion ConnectedRegions1 = RegionUnion.FillUp().Difference(RegionUnion).Connection();
	HRegion regioincap1 = ConnectedRegions1.SelectShape("area", "and", 30000, 50000).ShapeTrans("inner_rectangle1");
	HRegion regioincap2 = ConnectedRegions1.SelectShape("area", "and", 200000, 600000).OpeningCircle(30.5);
	HRegion regTrans = regioincap2.ShapeTrans("inner_rectangle1");
	Hlong Row13, Column13, Row23, Column23;
	
	regTrans.SmallestRectangle1(&Row13, &Column13, &Row23, &Column23);
	Hlong yy = 780;
	Hlong vv = 32;
	Hlong xx = 320;
	HRegion Rectangle1, Rectangle2;
	GenRectangle1(&Rectangle1, Row13 - yy, (Column13 + Column23) / 2 - vv, Row23 + yy, (Column13 + Column23) / 2 + vv);
	GenRectangle1(&Rectangle2, (Row13 + Row23) / 2 - vv, Column13 - xx, (Row13 + Row23) / 2 + vv, Column23 + xx);
	regioincap2 = regTrans.ConcatObj(Rectangle1).ConcatObj(Rectangle2).Union1();
	HRegion regioincap = regioincap1.ConcatObj(regioincap2).Union1();
	HImage ImgCapMidFull = imageCap.ReduceDomain(regioincap).CropDomain();
	ImgCapMidFull.GetImageSize(&Width6, &Height6);
	{
		HTuple rows, columns;
		ImgCapMidFull.Threshold(10, 255).GetRegionPoints(&rows, &columns);
		HTuple hValues = ImgCapMidFull.GetGrayval(rows, columns);
		imgFull.SetGrayval(rows + (Height5 - Height6) / 2, columns + (Width5 - Width6) / 2, hValues);
	}
	//imgFull.WriteImage("bmp", 0, "g:/imgFull");

	m_capImage = imgFull.RotateImage(90, "constant");
}

void BgaImageProcess::GenFullImageT32()
{
	PACKAGE_INFO info = StaticFunction::GetPackageInfo();

	int c = m_ballImageList.count();
	QList<HImage> imgListBall;

	HImage ImgCapMidFull;
	//HRegion b0, b1, s0, s1;
	for (int i = 0; i < c; i++)
	{
		HImage imageBall = m_ballImageList[i].CopyImage();
		//HImage imageCap;// = m_capImageList[i].CopyImage();
		HImage imageCrossMark;
		HImage imageSubstrate = m_substrateImageList[i].CopyImage();
		HRegion Rectangle;
		GenRectangle1(&Rectangle, 1200, 1000, 1500, 1500);
		double mean, dev;
		//rotate
		{

			HImage ImageGauss = imageBall.GaussFilter(3);
			mean = ImageGauss.Intensity(Rectangle, &dev);
			m_meanGray = mean;
			HRegion ConnectedRegions = imageBall.GaussFilter(3).Threshold(m_meanGray + 30, 255).DilationCircle(10.5).Union1().Connection();
			HRegion SelectedRegions = ConnectedRegions.SelectShapeStd("max_area", 70);
			HRegion RegionFillUp4 = ConnectedRegions.Difference(SelectedRegions).SelectShape(HTuple("width").Append(HTuple("height")), "and", HTuple(300).Append(HTuple(300)), HTuple(580).Append(HTuple(580))).FillUp().OpeningCircle(30.5).FillUp();
			double row, column, phi, len1, len2;
			RegionFillUp4.SmallestRectangle2(&row, &column, &phi, &len1, &len2);
			double rotateDeg = - phi * 180 / M_PI ;
			imageBall = imageBall.RotateImage(rotateDeg, "constant");
			imageSubstrate = m_substrateImageList[i].RotateImage(rotateDeg, "constant");

			/*if (info.crossMark)
			{
				imageCrossMark = m_crossMarkImageList[i].RotateImage(rotateDeg, "constant");
			}*/
		}

		HRegion ConnectedRegions = imageBall.GaussFilter(3).Threshold(m_meanGray + 30, 255).DilationCircle(10.5).Union1().Connection();
		HRegion SelectedRegions = ConnectedRegions.SelectShapeStd("max_area", 70);
		HRegion regionCap = ConnectedRegions.Difference(SelectedRegions).SelectShape(HTuple("width").Append(HTuple("height")), "and", HTuple(300).Append(HTuple(300)), HTuple(580).Append(HTuple(580))).FillUp().ErosionCircle(2.5);
		HTuple Row1, Column1, Row21, Column21;
		regionCap.SmallestRectangle1(&Row1, &Column1, &Row21, &Column21);
		HRegion Rectangle1;
		if (i == 0)
		{
			GenRectangle1(&Rectangle1, 0, (Column1 + Column21) / 2, Row21, 5000);
		}
		else if (i == 1)
		{
			GenRectangle1(&Rectangle1, 0, 0, Row21, (Column1 + Column21) / 2);
		}
		else if (i == 2)
		{
			GenRectangle1(&Rectangle1, Row21 - 12, 0, 5000, (Column1 + Column21) / 2);
		}
		else if (i == 3)
		{
			GenRectangle1(&Rectangle1, Row21 - 12, (Column1 + Column21) / 2, 5000, 5000);
		}

		HRegion regionBall = imageBall.GaussFilter(3).ReduceDomain(Rectangle1).Threshold(m_meanGray + 30, 255).OpeningCircle(1.5).Connection().SelectShape("width", "and", 18, 30).SelectShape("height", "and", 18, 30).SelectShape("area", "and", 300, 1000).DilationCircle(15.5).Union1().Connection().ClosingCircle(40.5).SelectShapeStd("max_area", 70).ErosionCircle(13.5).FillUp();
		HRegion RegionTrans2 = regionBall.ShapeTrans("rectangle1");
		Hlong  Row12, Column12, Row2, Column2;
		RegionTrans2.SmallestRectangle1(&Row12, &Column12, &Row2, &Column2);
		HRegion regionSub;
		HRegion r1;
		if (i == 0)
		{
			GenRectangle1(&r1, Row12 - info.edgeGap, Column12, Row2 , Column2 + info.edgeGap);
			regionSub = r1.Difference(RegionTrans2);
		}
		else if (i == 1)
		{
			GenRectangle1(&r1, Row12 - info.edgeGap, Column12 - info.edgeGap, Row2, Column2);
			regionSub = r1.Difference(RegionTrans2);
		}
		else if (i == 2)
		{
			GenRectangle1(&r1, Row12, Column12 - info.edgeGap, Row2 + info.edgeGap, Column2);
			regionSub = r1.Difference(RegionTrans2);
		}
		else if (i == 3)
		{
			GenRectangle1(&r1, Row12, Column12, Row2 + info.edgeGap, Column2 + info.edgeGap);
			regionSub = r1.Difference(RegionTrans2);
		}

		{
			HTuple hRows, hColuomns;
			regionSub.Union1().GetRegionPoints(&hRows, &hColuomns);
			HTuple hValues = imageSubstrate.GetGrayval(hRows, hColuomns);
			imageBall.SetGrayval(hRows, hColuomns, hValues);
		}
		imageBall = imageBall.ReduceDomain(regionBall.ConcatObj(regionSub).Union1()).CropDomain();
		imgListBall.append(imageBall);
	}


	//Hlong mergeGap = 20;
	Hlong w1, h1, w2, h2, w3, h3, w4, h4;

	imgListBall[0].GetImageSize(&w1, &h1);
	imgListBall[1].GetImageSize(&w2, &h2);
	imgListBall[2].GetImageSize(&w3, &h3);
	imgListBall[3].GetImageSize(&w4, &h4);

	Hlong maxC = MAX(w1 + w2, w3 + w4);
	Hlong maxR = MAX(h1 + h4, h2 + h3);
	HImage img, imgFull;
	GenImageConst(&img, "byte", maxC, maxR);
	GenImageProto(img, &imgFull, 0);
	Hlong difR[4] = { 0, 0, maxR - h3, maxR - h4 };
	Hlong difC[4] = { maxC-w1, 0, 0, maxC - w4 };
	for (int i = 0; i < imgListBall.count(); i++)
	{
		HImage imageBall = imgListBall[i];
		HTuple rows, columns;
		imageBall.GetDomain().GetRegionPoints(&rows, &columns);
		HTuple hValues = imageBall.GetGrayval(rows, columns);
		imgFull.SetGrayval(rows + difR[i], columns + difC[i], hValues);
	}

	m_ballImage = m_substrateImage = imgFull.CopyImage();

	HImage imageCap = m_capImageList[0];
	//rotate
	{
		HRegion Rectangle;
		GenRectangle1(&Rectangle, 1200, 1000, 1500, 1500);
		HImage ImageGauss = imageCap.GaussFilter(3);
		double dev;
		double mean = ImageGauss.Intensity(Rectangle, &dev);
		//m_meanGray = mean;
		HRegion ConnectedRegions = ImageGauss.Threshold(mean + 30, 255).DilationCircle(10.5).Union1().Connection();
		HRegion SelectedRegions = ConnectedRegions.SelectShapeStd("max_area", 70);
		HRegion RegionFillUp4 = ConnectedRegions.Difference(SelectedRegions).SelectShape(HTuple("width").Append(HTuple("height")), "and", HTuple(300).Append(HTuple(300)), HTuple(580).Append(HTuple(580))).FillUp().OpeningCircle(30.5).FillUp();
		double row, column, phi, len1, len2;
		RegionFillUp4.SmallestRectangle2(&row, &column, &phi, &len1, &len2);
		double rotateDeg = -phi * 180 / M_PI;
		imageCap = m_capImageList[0].RotateImage(rotateDeg, "constant");
	}
	{
		HRegion Rectangle;
		GenRectangle1(&Rectangle, 1200, 1000, 1500, 1500);
		HImage ImageGauss = imageCap.GaussFilter(3);
		double dev;
		double mean = ImageGauss.Intensity(Rectangle, &dev);
		//m_meanGray = mean;
		HRegion ConnectedRegions = ImageGauss.Threshold(mean + 30, 255).DilationCircle(10.5).Union1().Connection();
		HRegion SelectedRegions = ConnectedRegions.SelectShapeStd("max_area", 70);
		HRegion RegionFillUp4 = ConnectedRegions.Difference(SelectedRegions).SelectShape(HTuple("width").Append(HTuple("height")), "and", HTuple(300).Append(HTuple(300)), HTuple(580).Append(HTuple(580))).FillUp();
		ImgCapMidFull = imageCap.ReduceDomain(RegionFillUp4).CropDomain();
	}


	//middle caps
	Hlong Width5, Width6, Height5, Height6;
	imgFull.GetImageSize(&Width5, &Height5);
	ImgCapMidFull.GetImageSize(&Width6, &Height6);
	{
		HTuple rows, columns;
		ImgCapMidFull.GetDomain().GetRegionPoints(&rows, &columns);
		HTuple hValues = ImgCapMidFull.GetGrayval(rows, columns);
		imgFull.SetGrayval(rows + (Height5 - Height6) / 2, columns + (Width5 - Width6) / 2, hValues);
		HRegion rr;
		GenRectangle1(&rr, 0, 0, Height6, Width6);
		m_regionAllCaps = ImgCapMidFull.GetDomain().MoveRegion((Height5 - Height6) / 2, (Width5 - Width6) / 2);
	}

	m_capImage = imgFull;
}

ResultManager::ERROR_TYPE BgaImageProcess::GetInspectResult()
{
	InitParameter();
	PACKAGE_INFO info = StaticFunction::GetPackageInfo();
	QString type = BgaPackageManager::getInstance()->GetPackageType().toUpper();
	if (type.indexOf("T28") != -1)
	{
		try
		{
			GenFullImageT28();
		}
		catch (HalconCpp::HException e)
		{
			qDebug() << "Exception 1:" << e.ProcName() << e.ErrorCode() << e.ErrorMessage();
		}
	}
	else if (type.indexOf("T32") != -1)
	{
		try
		{
			GenFullImageT32();
		}
		catch (HalconCpp::HException e)
		{
			qDebug() << "Exception 1:" << e.ProcName() << e.ErrorCode() << e.ErrorMessage();
		}
	}
	ResultManager::ERROR_TYPE et = ResultManager::ERR_PASS;
	BOOL bIsCapOK = TRUE;
	if (info.capNumbers > 0)
	{
		qDebug() << "cap check start";
		try
		{
			bIsCapOK = CheckCapacitors2();
		}
		catch (HalconCpp::HOperatorException e)
		{
			qDebug() << "CheckCapacitors2:" << e.ErrorMessage() << e.ProcName();;
		}
	}
	qDebug() << "ball check start";
	if (!m_inspectParam.bCapDamaged)
	{
		m_listInspectEntity.clear();
	}
	try
	{
		CheckAllBalls();
	}
	catch (HalconCpp::HOperatorException e)
	{
		qDebug() << "CheckAllBalls:" << e.ErrorMessage() << e.ProcName();;
	}	
	int c1 = m_resultParam.countBallMiss + m_resultParam.regionDamagedBall.CountObj();
	BOOL bBall = c1 == 0;

	//BOOL bCM = TRUE;
	//if (info.crossMark && (bBall || m_ri.bVarify))
	//{
	//	qDebug() << "cross mark check start";
	//	if (m_crossMarkImage.IsInitialized())
	//	{
	//		try
	//		{
	//			bCM = CheckBallCrossMark(m_crossMarkImage);
	//		}
	//		catch (HalconCpp::HOperatorException e)
	//		{
	//			qDebug() << "CheckBallCrossMark:" << e.ErrorMessage() << e.ProcName();;
	//		}
	//	}
	//	else
	//	{
	//		qDebug() << "cross mark image error";
	//	}
	//}
	BOOL bSub = TRUE;
	if (m_inspectParam.bChipping) {
		qDebug() << "substrate check start";
		if (m_substrateImage.IsInitialized())
		{
			CheckSubstrate(m_substrateImage);
		}

		if (m_resultParam.regionDamagedEdge.CountObj() != 0)
		{
			bSub = FALSE;

		}
	}
	if (!bBall)
	{
		et = ResultManager::ERR_BALL_DAMAGE;
	}
	else
	{
		/*if (!bCM)
		{
			et = ResultManager::ERR_CROSS_MARK;
		}
		else*/
		{
			if (!bIsCapOK && m_inspectParam.bCapDamaged)
			{
				et = ResultManager::ERR_CAP_DAMAGE;
			}
			else
			{
				if (!bSub && m_inspectParam.bChipping)
				{
					et = ResultManager::ERR_SUBSTRATE_DAMAGE;
				}
			}
		}
	}

	//QTimer::singleShot(30, this, [=]() 
	//{
		SaveResultImage(et);
		m_substrateImageList.clear();
		m_ballImageList.clear();
		m_capImageList.clear();
		m_crossMarkImageList.clear();
	//});
	return et;
}

void BgaImageProcess::DrawResultToWindow()
{
	ResultManager::ERROR_TYPE res = m_curRes;
	if (res == ResultManager::ERR_MAX || !m_ballImage.IsInitialized())
	{
		return;
	}
	PACKAGE_INFO info = StaticFunction::GetPackageInfo();
	Hlong ImageWidth, ImageHeight;
	m_ballImage.GetImageSize(&ImageWidth, &ImageHeight);
	QHalconWindow *imageView = (QHalconWindow *)m_widget;
	//QRect rect = imageView->geometry();
	//double ratio = 1.0 * ImageWidth / ImageHeight;
	//imageView->setGeometry(rect.x()+(rect.width()-rect.height()*ratio)/2, rect.y(), rect.height()*ratio, rect.height());
	//rect = imageView->geometry();
	imageView->GetHalconBuffer()->ClearWindow();
	imageView->SetDispImageSize(ImageWidth, ImageHeight);
	if (ImageHeight > ImageWidth)
	{
		emit UpdateMainWndEvent();
	}
	
	imageView->GetHalconBuffer()->SetColor("green");
	imageView->GetHalconBuffer()->SetDraw("margin");

	if (m_resultParam.resultImage.Width().Type() != eTupleTypeEmpty)
	{
		imageView->GetHalconBuffer()->DispImage(m_resultParam.resultImage);
	}
	else 
	{
		if (m_substrateImage.IsInitialized())
			imageView->GetHalconBuffer()->DispImage(m_substrateImage);
		else
			imageView->GetHalconBuffer()->DispImage(m_ballImage);
	}
#ifndef QT_NO_DEBUG
	if (m_regionAllBalls.IsInitialized())
	{
		//qInfo() << "show edge area";
		imageView->GetHalconBuffer()->DispObj(m_regionAllBalls);
	}

	if (m_resultParam.regionDamagedEdge.IsInitialized())
	{
		imageView->GetHalconBuffer()->SetColor("magenta");
		imageView->GetHalconBuffer()->DispObj(m_resultParam.regionDamagedEdge);
		imageView->GetHalconBuffer()->SetDraw("margin");
	}
#else
	if (m_resultParam.countBallMiss > 0)
	{
		QString type = BgaPackageManager::getInstance()->GetPackageType().toUpper();
		if (type.indexOf("S231SLA2") != -1 || type.indexOf("T28") != -1)
		{
			if (m_regionAllBalls.IsInitialized())
			{
				//qInfo() << "show edge area";
				imageView->GetHalconBuffer()->DispObj(m_regionAllBalls);
			}
		}
	}
#endif
	if (m_inspectParam.bChipping)
	{
		if (m_regionSubstrate.IsInitialized())
		{
			//qInfo() << "show edge area";
			imageView->GetHalconBuffer()->DispObj(m_regionSubstrate);
		}

		if (m_resultParam.regionDamagedEdge.IsInitialized())
		{
			imageView->GetHalconBuffer()->SetColor("magenta");
			imageView->GetHalconBuffer()->DispObj(m_resultParam.regionDamagedEdge);
			imageView->GetHalconBuffer()->SetDraw("margin");
		}
	}

	if (m_inspectParam.bCapDamaged && info.capNumbers > 0)
	{
#ifndef QT_NO_DEBUG
		if (m_regionAllCaps.Area().Type() != eTupleTypeEmpty)
		{
			qInfo() << "show cap area";
			imageView->GetHalconBuffer()->SetColor("yellow");
			imageView->GetHalconBuffer()->DispObj(m_regionAllCaps);
		}
	/*	if (m_regionAllBalls.Area().Type() != eTupleTypeEmpty)
		{
			qInfo() << "show ball area";
			imageView->GetHalconBuffer()->SetColor("blue");
			imageView->GetHalconBuffer()->DispObj(m_regionAllBalls);
		}*/
#endif // DEBUG
		

		//imageView->GetHalconBuffer()->SetDraw("fill");
		if (m_resultParam.regionCap.Area().Type() != eTupleTypeEmpty)
		{
			//qInfo() << "show caps";
			imageView->GetHalconBuffer()->SetColor("blue");
			imageView->GetHalconBuffer()->DispObj(m_resultParam.regionCap);
		}
	}
	CONST int GAP = 20;

	
	QRect rect = m_widget->geometry(); 
	if (m_ri.bVarify)
	{
		HObject ho3;
		for (int i = 0; i < m_listCriticalEntity.count(); i++)
		{
			CRITICAL_ENTITY ie = m_listCriticalEntity[i];
			HObject circle;
			GenCircle(&circle, ie.coordinate.x(), ie.coordinate.y(), 15);
			if (!ho3.IsInitialized())
			{
				ho3 = circle;
			}
			else
			{
				ho3 = ho3.ConcatObj(circle);
			}
			imageView->GetHalconBuffer()->DispText(i + 1, "image", ie.coordinate.x() - 5, ie.coordinate.y() - 5, "white", "box_color", "black");

		}
		if (ho3.IsInitialized())
		{
			imageView->GetHalconBuffer()->SetLineWidth(2);
			imageView->GetHalconBuffer()->SetColor("blue");
			imageView->GetHalconBuffer()->DispObj(ho3);
			imageView->GetHalconBuffer()->SetDraw("margin");
			imageView->GetHalconBuffer()->SetLineWidth(1);
		}
	}

	if (res == ResultManager::ERR_PASS)
	{
		HTuple font = imageView->GetHalconBuffer()->QueryFont();
		imageView->GetHalconBuffer()->SetFont(font + "-Bold-30");
		imageView->GetHalconBuffer()->DispText("Pass", "window", "top", "right", "green", "box_color", "black");
		imageView->GetHalconBuffer()->SetFont(font + "-Bold-13");
		int height = 50;

		QString str1 = QString("Number of Capacitors:%1, Check Capacitors:%2").arg(info.capNumbers).arg(info.capNumbers);
		QString str2 = QString("Number of Balls:%1, Check Balls:%2").arg(info.ballNumbers).arg(info.ballNumbers);
		QTextCodec *code = QTextCodec::codecForName("GB2312");

		if (m_inspectParam.bCapDamaged)
		{
			if (info.capNumbers > 0)
			{
				std::string name1 = code->fromUnicode(str1).data();

				imageView->GetHalconBuffer()->DispText(name1.c_str(), "window", height, "right", "green", "box_color", "black");

				height += GAP;
			}
		}

		if (m_inspectParam.bBallDamaged)
		{
			std::string name2 = code->fromUnicode(str2).data();
			imageView->GetHalconBuffer()->DispText(name2.c_str(), "window", height, "right", "green", "box_color", "black");

			height += GAP;
		}
	}
	else {

		HTuple font = imageView->GetHalconBuffer()->QueryFont();
		imageView->GetHalconBuffer()->SetFont(font + "-Bold-30");
		imageView->GetHalconBuffer()->DispText("Fail", "window", "top", "right", "red", "box_color", "black");
		//imageView->GetHalconBuffer()->SetFont(font + "-Bold-24");
		//imageView->GetHalconBuffer()->DispText("Reason:", "window", "bottom",
		//	"left", "green", "box_color", "black");
		imageView->GetHalconBuffer()->SetFont(font + "-Bold-13");
		int height = 50;
		if (res == ResultManager::ERR_BALL_DAMAGE /*|| res == ResultManager::ERR_CROSS_MARK*/)
		{
			{
				QString str = QString("Number of balls:%1, Check balls:%2").arg(info.ballNumbers).arg(info.ballNumbers - m_resultParam.countBallMiss);
				QTextCodec *code = QTextCodec::codecForName("GB2312");
				std::string name = code->fromUnicode(str).data();

				if (m_resultParam.countBallMiss != 0)
				{
					imageView->GetHalconBuffer()->DispText(name.c_str(), "window", height, "right", "red", "box_color", "black");
				}
				else {
					imageView->GetHalconBuffer()->DispText(name.c_str(), "window", height, "right", "green", "box_color", "black");
				}
				height += GAP;
			}
			if (m_resultParam.countBallMiss > 0)
			{
				HRegion reDam = m_resultParam.regionDamagedBall.Connection().SelectShape("area", "and", 2, 10000000);
				int count = 0;
				if (reDam.IsInitialized())
				{
					count = reDam.CountObj();
				}
				QString str = QString("%1 Ball(s) damaged").arg(abs(m_resultParam.countBallMiss) + count);
				QTextCodec *code = QTextCodec::codecForName("GB2312");
				std::string name = code->fromUnicode(str).data();
				imageView->GetHalconBuffer()->DispText(name.c_str(), "window", height, "right", "red", "box_color", "black");
				height += GAP;
			}
			else
			{
				HRegion reDam = m_resultParam.regionDamagedBall.Connection().SelectShape("area", "and", 2, 10000000);
				QString str = QString("%1 Ball(s) damaged").arg(reDam.CountObj());
				QTextCodec *code = QTextCodec::codecForName("GB2312");
				std::string name = code->fromUnicode(str).data();
				imageView->GetHalconBuffer()->DispText(name.c_str(), "window", height, "right", "red", "box_color", "black");
				height += GAP;
			}
		}
		else if (res == ResultManager::ERR_SUBSTRATE_DAMAGE)
		{
			imageView->GetHalconBuffer()->DispText("Substrate damaged", "window", height, "right", "red", "box_color", "black");
			height += GAP;
		}
		else if (res == ResultManager::ERR_CAP_DAMAGE)
		{
			{
				QString str = QString("%1 Capacitor(s) damaged").arg(abs(info.capNumbers - m_resultParam.countCap));
				QTextCodec *code = QTextCodec::codecForName("GB2312");
				std::string name = code->fromUnicode(str).data();

				imageView->GetHalconBuffer()->DispText(name.c_str(), "window", height, "right", "red", "box_color", "black");
				height += GAP;
			}

			{
				QString str = QString("Number of Capacitors:%1, Check Capacitors:%2").arg(info.capNumbers).arg(m_resultParam.countCap);
				QTextCodec *code = QTextCodec::codecForName("GB2312");
				std::string name = code->fromUnicode(str).data();
				imageView->GetHalconBuffer()->DispText(name.c_str(), "window", height, "right", "red", "box_color", "black");
				height += GAP;
			}
		}

		HObject ho3;
		for (int i = 0; i < m_listInspectEntity.count(); i++)
		{
			INSPECT_ENTITY ie = m_listInspectEntity[i];
			if (m_inspectParam.bShowNumLabel)
			{
				imageView->GetHalconBuffer()->DispText(i + 1, "image", ie.coordinate.x() - 5, ie.coordinate.y() - 5, "yellow", "box_color", "black");
			}
			
			HObject circle;
			if (ie.reason == FAIL_CAP_AREA)
			{
				GenCircle(&circle, ie.coordinate.x(), ie.coordinate.y(), 20);
			}
			else if (ie.reason <= FAIL_BALL_CM)
			{
				GenCircle(&circle, ie.coordinate.x(), ie.coordinate.y(), 12);
			}
			else
			{
				continue;
			}
			if (!ho3.IsInitialized())
			{
				ho3 = circle;
			}
			else
			{
				ho3 = ho3.ConcatObj(circle);
			}
		}
		if (ho3.IsInitialized())
		{
			imageView->GetHalconBuffer()->SetLineWidth(2);
			imageView->GetHalconBuffer()->SetColor("magenta");
			imageView->GetHalconBuffer()->DispObj(ho3);
			imageView->GetHalconBuffer()->SetDraw("margin");
			imageView->GetHalconBuffer()->SetLineWidth(1);
		}

		if (m_resultParam.regionDamagedBall.IsInitialized())
		{
			imageView->GetHalconBuffer()->SetLineWidth(2);
			imageView->GetHalconBuffer()->SetColor("magenta");
			imageView->GetHalconBuffer()->DispObj(m_resultParam.regionDamagedBall.Union1());
			imageView->GetHalconBuffer()->SetDraw("margin");
			imageView->GetHalconBuffer()->SetLineWidth(1);
		}
		//qpoint借用定义
		QPoint frArray[FAIL_REASON_NUM];
		for (int i = 0; i < FAIL_REASON_NUM; i++)
		{
			frArray[i] = QPoint(0, 0);
		}
		for (int i = 0; i < m_listInspectEntity.count(); i++)
		{
			INSPECT_ENTITY ie = m_listInspectEntity[i];
			if (frArray[ie.reason].x() == 0)
			{
				frArray[ie.reason].setX(i + 1);
				frArray[ie.reason].setY(i + 1);
			}
			else
			{
				frArray[ie.reason].setY(i + 1);
			}
		}
		int height2 = rect.height() - 35;

		if (frArray[FAIL_BALL_MISS].x() > 0)
		{
			int k1 = frArray[FAIL_BALL_MISS].x();
			int k2 = frArray[FAIL_BALL_MISS].y();
			INSPECT_ENTITY ie = m_listInspectEntity[k1 - 1];

			QString str = QString("[%1~%2] %3 %4").arg(k1).arg(k2).arg(ie.reasonDesc).arg(ie.parameterDesc);
			imageView->GetHalconBuffer()->DispText(HString(str.toUtf8()), "window", height2, "left", "green", "box_color", "black");
			height2 -= GAP;
		}
		if (frArray[FAIL_BALL_NOT_ROUND].x() > 0)
		{
			int k1 = frArray[FAIL_BALL_NOT_ROUND].x();
			int k2 = frArray[FAIL_BALL_NOT_ROUND].y();
			INSPECT_ENTITY ie = m_listInspectEntity[k1 - 1];

			QString str = QString("[%1~%2] %3 (%4 ~ 100)").arg(k1).arg(k2).arg(ie.reasonDesc).arg(m_inspectParam.miniCircularity);
			imageView->GetHalconBuffer()->DispText(HString(str.toUtf8()), "window", height2, "left", "green", "box_color", "black");
			height2 -= GAP;
		}
		if (frArray[FAIL_BALL_TOO_SMALL].x() > 0)
		{
			int k1 = frArray[FAIL_BALL_TOO_SMALL].x();
			int k2 = frArray[FAIL_BALL_TOO_SMALL].y();
			INSPECT_ENTITY ie = m_listInspectEntity[k1 - 1];
			QString str = QString("[%1~%2] %3 (%4 ~ %5)").arg(k1).arg(k2).arg(ie.reasonDesc).arg(m_inspectParam.miniAreaRatio).arg(m_inspectParam.maxAreaRatio);
			imageView->GetHalconBuffer()->DispText(HString(str.toUtf8()), "window", height2, "left", "green", "box_color", "black");
			height2 -= GAP;
		}
		if (frArray[FAIL_BALL_TOO_BIG].x() > 0)
		{
			int k1 = frArray[FAIL_BALL_TOO_BIG].x();
			int k2 = frArray[FAIL_BALL_TOO_BIG].y();
			INSPECT_ENTITY ie = m_listInspectEntity[k1 - 1];
			QString str = QString("[%1~%2] %3 (%4 ~ %5)").arg(k1).arg(k2).arg(ie.reasonDesc).arg(m_inspectParam.miniAreaRatio).arg(m_inspectParam.maxAreaRatio);
			imageView->GetHalconBuffer()->DispText(HString(str.toUtf8()), "window", height2, "left", "green", "box_color", "black");
			height2 -= GAP;
		}
		if (frArray[FAIL_BALL_SHADOW_TOO_BIG].x() > 0)
		{
			int k1 = frArray[FAIL_BALL_SHADOW_TOO_BIG].x();
			int k2 = frArray[FAIL_BALL_SHADOW_TOO_BIG].y();
			INSPECT_ENTITY ie = m_listInspectEntity[k1 - 1];
			QString str = QString("[%1~%2] %3 (0 ~%4)").arg(k1).arg(k2).arg(ie.reasonDesc).arg(m_inspectParam.miniDamagedRatio);
			imageView->GetHalconBuffer()->DispText(HString(str.toUtf8()), "window", height2, "left", "green", "box_color", "black");
			height2 -= GAP;
		}
		if (frArray[FAIL_BALL_CM].x() > 0)
		{
			int k1 = frArray[FAIL_BALL_CM].x();
			int k2 = frArray[FAIL_BALL_CM].y();
			INSPECT_ENTITY ie = m_listInspectEntity[k1 - 1];
			QString str = QString("[%1~%2] %3 %4").arg(k1).arg(k2).arg(ie.reasonDesc).arg(ie.parameterDesc);
			imageView->GetHalconBuffer()->DispText(HString(str.toUtf8()), "window", height2, "left", "green", "box_color", "black");
			height2 -= GAP;
		}
		if (frArray[FAIL_BALL_CRESCENT].x() > 0)
		{
			int k1 = frArray[FAIL_BALL_CRESCENT].x();
			int k2 = frArray[FAIL_BALL_CRESCENT].y();
			INSPECT_ENTITY ie = m_listInspectEntity[k1 - 1];

			QString str = QString("[%1~%2] %3 %4").arg(k1).arg(k2).arg(ie.reasonDesc).arg(ie.parameterDesc);
			imageView->GetHalconBuffer()->DispText(HString(str.toUtf8()), "window", height2, "left", "green", "box_color", "black");
			height2 -= GAP;
		}
		if (frArray[FAIL_CAP_AREA].x() > 0)
		{
			int k1 = frArray[FAIL_CAP_AREA].x();
			int k2 = frArray[FAIL_CAP_AREA].y();
			INSPECT_ENTITY ie = m_listInspectEntity[k1 - 1];
			QString str = QString("[%1~%2] %3 %4").arg(k1).arg(k2).arg(ie.reasonDesc).arg(ie.parameterDesc);
			//QString str = QString("[%1~%2] %3 (0 ~%4)").arg(k1 + 1).arg(k2 + 1).arg(ie.reasonDesc).arg(m_inspectParam.miniDamagedRatio);
			imageView->GetHalconBuffer()->DispText(HString(str.toUtf8()), "window", height2, "left", "green", "box_color", "black");
			height2 -= GAP;
		}
		if (frArray[FAIL_SUBSTRATE_AREA].x() > 0)
		{
			int k1 = frArray[FAIL_SUBSTRATE_AREA].x();
			int k2 = frArray[FAIL_SUBSTRATE_AREA].y();
			INSPECT_ENTITY ie = m_listInspectEntity[k1 - 1];
			QString str = QString("[%1~%2] %3 (0 ~ %5)").arg(k1).arg(k2).arg(ie.reasonDesc).arg(m_inspectParam.miniChippingArea);
			imageView->GetHalconBuffer()->DispText(HString(str.toUtf8()), "window", height2, "left", "green", "box_color", "black");
			height2 -= GAP;
		}
	}
	imageView->GetHalconBuffer()->FlushBuffer();
}

void BgaImageProcess::SaveResultImage(ResultManager::ERROR_TYPE res)
{
	m_curRes = res;
	if (m_ballImage.IsInitialized())
	{
		DrawResultToWindow();
	}

	bool bRes = ResultManager::ERR_PASS == m_curRes;
	if (!m_inspectParam.bOnlySaveFail || (!bRes &&m_inspectParam.bOnlySaveFail))
	{
		QHalconWindow *imageView = (QHalconWindow *)m_widget;
		HImage img = imageView->GetHalconBuffer()->DumpWindowImage();
		ImageSaveManager *ism = ImageSaveManager::getInstance();
		ism->AddImageList(m_ballImageList, m_capImageList, m_substrateImageList, m_ri.lotName, m_time, bRes, img, 0);
	}
	//qInfo() << "show result to window";

	//if (m_ri.bVarify)
	//{
	//	m_iVerifyCount++;
	//	GenVerifyTestResult(res);
	//}
	//QString currentdate = m_time.toString("yyyy-MM-dd");
	//QString currentime = m_time.toString("hh_mm_ss");

	//QString dirStr = QString("%1/%2").arg(m_path).arg(currentdate);
	//if (m_ri.lotName.length() > 0)
	//{
	//	dirStr = QString("%1/%2").arg(m_path).arg(m_ri.lotName);
	//}
	//if (m_inspectParam.bSeperateFolder)
	//{
	//	dirStr = QString("%1/%2_%3").arg(dirStr).arg(BgaPackageManager::getInstance()->GetPackageType()).arg(m_iInspectCount / m_inspectParam.iCountForSeperateFolder + 1);
	//	m_iInspectCount++;
	//}
	//QDir dir;
	//if (!dir.exists(dirStr))
	//{
	//	dir.mkpath(dirStr);
	//	//qDebug() << "mkpath" << dir_str << res;
	//}



	//QString appName = QCoreApplication::applicationName();
	//QSettings app(appName, "Debug");
	//QStringList list;
	//list << "bmp" << "png fastest" << "png";

	//int index = app.value("imagetype").toInt();
	//if (index >= list.count() || index < 0)
	//{
	//	index = 0;
	//}
	//QString ext = list[index];
	//if (!m_inspectParam.bOnlySaveFail ||  res != ResultManager::ERR_PASS)
	//{
	//	PACKAGE_INFO info = StaticFunction::GetPackageInfo();
	//	if (info.listAction.length() == 0)
	//	{
	//		{
	//			QString file = QString("%1/%2_edge1").arg(dirStr).arg(currentime);
	//			if (m_substrateImageList.length() > 0 && m_substrateImageList.first().IsInitialized())
	//			{
	//				m_substrateImageList.first().WriteImage(ext.toUtf8(), 0, file.toStdString().c_str());
	//			}
	//		}
	//		{
	//			QString file = QString("%1/%2_ball1").arg(dirStr).arg(currentime);
	//			if (m_ballImageList.length() > 0 && m_ballImageList.first().IsInitialized())
	//			{
	//				m_ballImageList.first().WriteImage(ext.toUtf8(), 0, file.toStdString().c_str());
	//			}
	//		}
	//		if(info.capNumbers > 0)
	//		{
	//			QString file = QString("%1/%2_cap1").arg(dirStr).arg(currentime);
	//			if (m_capImageList.length() > 0 && m_capImageList.first().IsInitialized())
	//			{
	//				m_capImageList.first().WriteImage(ext.toUtf8(), 0, file.toStdString().c_str());
	//			}
	//		}
	//		
	//		/*if (info.crossMark > 0)
	//		{
	//			QString file = QString("%1/%2_cm1").arg(dirStr).arg(currentime);
	//			if (m_crossMarkImageList.length() > 0 && m_crossMarkImageList.first().IsInitialized())
	//			{
	//				m_crossMarkImageList.first().WriteImage(ext.toUtf8(), 0, file.toStdString().c_str());
	//			}
	//		}*/
	//	}
	//	else
	//	{
	//		for (int i = 1; i <= info.listAction.length(); i++)
	//		{
	//			ACTION_CONFIG ac = info.listAction[i-1];
	//			if (ac.catchSubstrate)
	//			{
	//				QString file = QString("%1/%2_edge%3").arg(dirStr).arg(currentime).arg(i);
	//				if (m_substrateImageList.count() >= i && m_substrateImageList[i - 1].IsInitialized())
	//				{
	//					m_substrateImageList[i - 1].WriteImage("bmp", 0, file.toUtf8());
	//				}
	//			}
	//			if (ac.catchBall)
	//			{
	//				QString file = QString("%1/%2_ball%3").arg(dirStr).arg(currentime).arg(i);
	//				if (m_ballImageList.count() >= i && m_ballImageList[i - 1].IsInitialized())
	//				{
	//					m_ballImageList[i - 1].WriteImage("bmp", 0, file.toUtf8());
	//				}
	//			}
	//			if (ac.catchCap && info.capNumbers > 0)
	//			{
	//				QString file = QString("%1/%2_cap%3").arg(dirStr).arg(currentime).arg(i);
	//				if (m_capImageList.count() >= i && m_capImageList[i - 1].IsInitialized())
	//				{
	//					m_capImageList[i - 1].WriteImage("bmp", 0, file.toUtf8());
	//				}
	//			}
	//		/*	if(ac.catchCM && info.crossMark > 0)
	//			{
	//				QString file = QString("%1/%2_cm%3").arg(dirStr).arg(currentime).arg(i);
	//				if (m_crossMarkImageList.count() >= i && m_crossMarkImageList[i - 1].IsInitialized())
	//				{
	//					m_crossMarkImageList[i - 1].WriteImage("bmp", 0, file.toUtf8());
	//				}
	//			}*/
	//		}
	//	}

	//	{
	//		QString str = res == ResultManager::ERR_PASS ? "P" : "F";
	//		QString fileReuslt = QString("%1/%2_%3").arg(dirStr).arg(currentime).arg(str);
	//		QHalconWindow *imageView = (QHalconWindow *)m_widget;
	//		imageView->GetHalconBuffer()->DumpWindow("bmp", fileReuslt.toStdString().c_str());
	//	}
	//}
}

void BgaImageProcess::GenVerifyTestResult(ResultManager::ERROR_TYPE res)
{

	//QXlsx::Document xlsxNew;
	QString appName = QCoreApplication::applicationName();
	QSettings app(appName, "Debug");
	QString dir_str = QString("%1/VerifyTestReport").arg(QCoreApplication::applicationDirPath());
	//  qDebug()<<dir_str;
		//检查目录是否存在，若不存在则新建
	QDir dir;
	if (!dir.exists(dir_str))
	{
		dir.mkpath(dir_str);
		//  qDebug() << "新建目录是否成功" <<dir_str<< res;
	}

	QString path = QString("%1/%2.xls").arg(dir_str).arg(app.value("StartTime").toString());
	QXlsx::Document xlsxNew(path);



	int circle = 1 + (m_iVerifyCount - 1) / m_ri.chipNum;
	int count = m_iVerifyCount - m_ri.chipNum*(circle - 1);
	//qDebug() << m_iRunCount << circle << count;

	if (count == 1)
	{
		xlsxNew.write(2 + circle, 1, QString("Test%1").arg(circle));
	}
	const int R_WIDTH = 5;
	QString str = xlsxNew.read(1, count * R_WIDTH - 2).toString();
	if (str.isEmpty())
	{
		QXlsx::Format format2;/*重新设置另一个单元的样式*/
		format2.setFontBold(true);/*设置加粗*/
		//format2.setFontUnderline(QXlsx::Format::FontUnderlineDouble);/*下双划线*/
		//format2.setFillPattern(QXlsx::Format::PatternLightGray);/*填充方式*/
		format2.setPatternBackgroundColor(QColor(150, 150, 150, 100));
		format2.setFontColor(QColor(255, 0, 0, 255));
		format2.setHorizontalAlignment(QXlsx::Format::AlignHCenter);

		/*xlsxNew.write(1, count * 3, "");
		xlsxNew.write(1, count * 3 + 1, "");*/
		QXlsx::CellRange r = QXlsx::CellRange(1, count * R_WIDTH - 2, 1, count * R_WIDTH + 1);
		xlsxNew.read(1, count * R_WIDTH - 2);
		xlsxNew.mergeCells(r);
		xlsxNew.write(1, count * R_WIDTH - 2, QString("Unit%1").arg(count), format2);
	}

	xlsxNew.write(2, count * R_WIDTH - 2, "Result");
	xlsxNew.write(2, count * R_WIDTH - 1, "Fail Reason");
	xlsxNew.write(2, count * R_WIDTH, "Parameter");
	xlsxNew.write(2, count * R_WIDTH + 1, "Time");

	if (res == ResultManager::ERR_PASS)
	{
		xlsxNew.write(2 + circle, count * R_WIDTH - 2, "P");
		if (m_listCriticalEntity.count() > 0)
		{
			QString reason, param;
			for (int i = 0; i < m_listCriticalEntity.count(); i++)
			{
				CRITICAL_ENTITY ie = m_listCriticalEntity[i];

				QString reason1 = QString("[%1]%2\n").arg(i + 1).arg(ie.reasonDesc);
				QString param1 = QString("[%1]%2\n").arg(i + 1).arg(ie.parameterDesc);
				reason.append(reason1);
				param.append(param1);
			}
			xlsxNew.write(2 + circle, count * R_WIDTH - 1, reason.left(reason.size() - 1));
			xlsxNew.write(2 + circle, count * R_WIDTH, param.left(param.size() - 1));
		}
		xlsxNew.write(2 + circle, count * R_WIDTH + 1, m_time.toString("hh_mm_ss"));
	}
	else
	{

		QString reason, param;
		if (m_listInspectEntity.count() > 0)
		{

			for (int i = 0; i < m_listInspectEntity.count(); i++)
			{
				INSPECT_ENTITY ie = m_listInspectEntity[i];

				QString reason1 = QString("[%1]%2\n").arg(i + 1).arg(ie.reasonDesc);
				QString param1 = QString("[%1]%2\n").arg(i + 1).arg(ie.parameterDesc);
				reason.append(reason1);
				param.append(param1);
			}
		}

		if (m_listCriticalEntity.count() > 0)
		{
			for (int i = 0; i < m_listCriticalEntity.count(); i++)
			{
				CRITICAL_ENTITY ie = m_listCriticalEntity[i];

				QString reason1 = QString("[%1]%2\n").arg(i + 1).arg(ie.reasonDesc);
				QString param1 = QString("[%1]%2\n").arg(i + 1).arg(ie.parameterDesc);
				reason.append(reason1);
				param.append(param1);
			}
		}

		xlsxNew.write(2 + circle, count * R_WIDTH - 2, "F");
		xlsxNew.write(2 + circle, count * R_WIDTH - 1, reason.left(reason.size() - 1));
		xlsxNew.write(2 + circle, count * R_WIDTH, param.left(param.size() - 1));
		xlsxNew.write(2 + circle, count * R_WIDTH + 1, m_time.toString("hh_mm_ss"));

	}

	xlsxNew.saveAs(path);
}